Jak sprawdzić, czy plik istnieje w skryptach Linux Bash?

Opublikowany: 2022-08-18
Laptop z systemem Linux wyświetlający monit o bash
fatmawati achmad zaenuri/Shutterstock.com

Jeśli skrypt Linux Bash opiera się na obecności pewnych plików lub katalogów, nie może po prostu zakładać, że tak. Musi sprawdzić, czy na pewno są obecne. Oto jak to zrobić.

Nie zakładaj niczego

Kiedy piszesz skrypt, nie możesz zakładać, co jest, a czego nie ma na komputerze. Jest to podwójnie prawdziwe, jeśli skrypt będzie rozpowszechniany i uruchamiany na wielu różnych komputerach. Prędzej czy później skrypt zostanie uruchomiony na komputerze, który nie spełnia Twoich założeń, a skrypt zakończy się niepowodzeniem lub będzie działał nieprzewidywalnie.

Wszystko, co cenimy lub tworzymy na komputerze, jest przechowywane w pliku o określonym formacie, a wszystkie te pliki znajdują się w katalogu. Skrypty mogą odczytywać, zapisywać, zmieniać nazwy, usuwać i przenosić pliki i katalogi — wszystko to, co możesz zrobić w wierszu poleceń.

Zaletą, jaką masz jako człowiek, jest to, że możesz zobaczyć zawartość katalogu i wiesz, czy plik istnieje, czy nie – lub czy oczekiwany katalog w ogóle istnieje. Jeśli skrypt zawodzi podczas manipulowania plikami, może to mieć poważne i szkodliwe skutki.

Bash zapewnia kompleksowy zestaw testów, których można użyć do wykrywania plików i katalogów oraz testowania wielu ich atrybutów. Włączenie ich do skryptów jest łatwe, ale korzyści pod względem niezawodności i precyzyjnej kontroli są znaczne.

POWIĄZANE: Jak używać testów warunkowych z podwójnym nawiasem w systemie Linux

Zakres badań

Łącząc instrukcję if z odpowiednim testem z dużej kolekcji testów plików i katalogów, możemy łatwo określić, czy plik istnieje, czy jest wykonywalny, zapisywalny i wiele więcej.

  • -b : Zwraca prawdę, jeśli plik jest blokowym plikiem specjalnym.
  • -c : Zwraca prawdę, jeśli plik jest znakiem specjalnym.
  • -d : Zwraca prawdę, jeśli „plik” jest katalogiem.
  • -e : Zwraca prawdę, jeśli plik istnieje.
  • -f : Zwraca prawdę, jeśli plik istnieje i jest zwykłym plikiem.
  • -g : Zwraca prawdę, jeśli plik ma ustawione uprawnienia setgid ( chmod g+ ).
  • -h : Zwraca prawdę, jeśli plik jest dowiązaniem symbolicznym.
  • -L : Zwraca prawdę, jeśli plik jest dowiązaniem symbolicznym.
  • -k : Zwraca prawdę, jeśli ma ustawiony bit Sticky ( chmod +t ).
  • -p : Zwraca prawdę, jeśli plik jest nazwanym potokiem.
  • -r : Zwraca prawdę, jeśli plik jest czytelny.
  • -s : Zwraca prawdę, jeśli plik istnieje i nie jest pusty.
  • -S : Zwraca prawdę, jeśli plik jest gniazdem.
  • -t : Zwraca prawdę, jeśli deskryptor pliku jest otwarty w terminalu.
  • -u : Zwraca prawdę, jeśli plik ma ustawione uprawnienia setuid ( chmod u+ ).
  • -w : Zwraca prawdę, jeśli plik jest zapisywalny.
  • -x : Zwraca prawdę, jeśli plik jest wykonywalny.
  • -O : Zwraca prawdę, jeśli należy do Ciebie.
  • -G : Zwraca prawdę, jeśli należy do twojej grupy.
  • -N : Zwraca prawdę, jeśli plik został zmodyfikowany od czasu ostatniego odczytu.
  • ! : Logiczny operator NOT.
  • && : Operator logiczny AND.
  • || : Operator logiczny OR.

Lista zaczyna się od -b , ponieważ test -a jest przestarzały i zastąpiony testem -e .

POWIĄZANE: Jak korzystać z SUID, SGID i Sticky Bits w systemie Linux

Korzystanie z testów w skryptach

Ogólna instrukcja testu if jest prostą konstrukcją skryptową. Porównanie wewnątrz podwójnych nawiasów „ [[ ]] ” wykorzystuje test -f w celu określenia, czy istnieje zwykły plik o tej nazwie.

Skopiuj tekst tego skryptu do edytora i zapisz go w pliku o nazwie „script1.sh” i użyj chmod , aby uczynić go wykonywalnym.

 #!/kosz/bash

jeśli [[ -f $1 ]] 

następnie 

  echo "Plik $1 istnieje." 

w przeciwnym razie 

  echo "Nie można znaleźć pliku $1." 

fi

Musisz przekazać nazwę pliku do skryptu w linii poleceń.

 chmod +x skrypt1.sh 

Tworzenie skryptu wykonywalnego za pomocą chmod

Musisz to zrobić z każdym skryptem, jeśli chcesz wypróbować inne przykłady z artykułu.

Wypróbujmy skrypt na prostym pliku tekstowym.

 ./script1.sh plik-testowy.txt 

Uruchamianie script1.sh na zwykłym pliku

Plik istnieje i skrypt poprawnie zgłasza ten fakt. Jeśli usuniemy plik i spróbujemy ponownie, test powinien zakończyć się niepowodzeniem, a skrypt powinien nam to zgłosić.

 ./script1.sh plik-testowy.txt 

Uruchamianie script1.sh na pliku, który nie istnieje

W rzeczywistej sytuacji skrypt musiałby podjąć odpowiednie działania. Być może oznacza to błąd i zatrzymuje się. Może tworzy plik i kontynuuje. Może skopiować coś z katalogu kopii zapasowej, aby zastąpić brakujący plik. Wszystko zależy od przeznaczenia scenariusza. Ale przynajmniej teraz skrypt jest w stanie podjąć decyzję na podstawie wiedzy, czy plik jest obecny, czy nie.

Flaga -f sprawdza, czy plik jest obecny i jest „zwykłym” plikiem. Innymi słowy, nie jest to coś, co wydaje się być plikiem, ale nim nie jest, na przykład plik urządzenia.

Użyjemy ls, aby sprawdzić, czy plik „/dev/random” istnieje, a następnie zobaczymy, co zrobi z niego skrypt.

 ls -lh /dev/losowe
 ./skrypt /dev/losowy 

Uruchamianie script1.sh na pliku urządzenia

Ponieważ nasz skrypt testuje zwykłe pliki, a „/dev/random” jest plikiem urządzenia, test nie powiedzie się. Bardzo często, aby dotrzeć do sedna tego, czy plik istnieje, musisz uważnie wybrać test, którego używasz, lub musisz użyć kilku testów.

To jest „script2.sh”, który testuje zwykłe pliki i pliki urządzeń znakowych.

 #!/kosz/bash

jeśli [[ -f $1 ]]
następnie
  echo "Plik $1 istnieje."
w przeciwnym razie
  echo "Brak pliku $1 lub nie jest to zwykły plik."
fi

jeśli [[ -c $1 ]]
następnie
  echo "Plik $1 jest plikiem urządzenia znakowego."
w przeciwnym razie
  echo "Brak pliku $1 lub nie jest to plik specjalny." 
fi

Jeśli uruchomimy ten skrypt na pliku urządzenia „/dev/random”, pierwszy test zakończy się niepowodzeniem, czego oczekujemy, a drugi test zakończy się sukcesem. Rozpoznaje plik jako plik urządzenia.

 ./script2.sh /dev/losowo 

Uruchamianie script2.sh na pliku urządzenia znakowego

W rzeczywistości rozpoznaje go jako plik urządzenia znakowego . Niektóre pliki urządzeń są plikami urządzeń blokowych. W obecnej sytuacji nasz skrypt sobie z tym nie poradzi.

 ./script2.sh /dev/sda 

Uruchamianie scrip2.sh na pliku urządzenia blokowego

Możemy użyć operatora logicznego OR i dołączyć kolejny test w drugiej instrukcji if. Tym razem, niezależnie od tego, czy plik jest plikiem urządzenia znakowego, czy plikiem urządzenia blokowego, test zwróci true. To jest „script3.sh”.

 #!/kosz/bash

jeśli [[ -f $1 ]]
następnie
  echo "Plik $1 istnieje."
w przeciwnym razie
  echo "Brak pliku $1 lub nie jest to zwykły plik."
fi

jeśli [[ -c $1 || -b $1]]
następnie
  echo "Plik $1 jest plikiem znakowym lub blokowym."
w przeciwnym razie
  echo "Brak pliku $1 lub nie jest to plik specjalny." 
fi

Ten skrypt rozpoznaje zarówno pliki urządzeń znakowych, jak i urządzenia blokowe.

 ./script3.sh /dev/losowo
 ./script3.sh /dev/sda 

script3.sh poprawnie obsługuje pliki znakowe i blokowe

Jeśli ważne jest dla Ciebie rozróżnienie pomiędzy różnymi typami plików urządzeń, możesz użyć zagnieżdżonych instrukcji if . To jest „script4.sh”.

 #!/kosz/bash

jeśli [[ -f $1 ]]
następnie
  echo "Plik $1 istnieje."
w przeciwnym razie
  echo "Brak pliku $1 lub nie jest to zwykły plik."
fi

jeśli [[ -c $1 ]]
następnie
  echo "Plik $1 jest plikiem urządzenia znakowego."
w przeciwnym razie
  jeśli [[ -b $1 ]]
  następnie
    echo "Plik $1 jest plikiem urządzenia blokowego." 
  w przeciwnym razie
    echo "Brak pliku $1 lub nie jest to plik urządzenia."
  fi
fi

Ten skrypt rozpoznaje i kategoryzuje zarówno pliki urządzeń znakowych, jak i urządzenia blokowe.

 ./script4.sh /dev/losowo
 ./script4.sh /dev/sda 

script8.sh poprawnie identyfikuje pliki znakowe i blokowe

Używając operatora logicznego AND możemy przetestować kilka cech jednocześnie. To jest „script5.sh”. Sprawdza, czy plik istnieje, a skrypt ma do niego uprawnienia do odczytu i zapisu.

 #!/kosz/bash

if [[ -f $1 && -r $1 && -w $1 ]]
następnie
  echo "Plik $1 istnieje i mamy uprawnienia do odczytu/zapisu."
w przeciwnym razie
  echo "Brakuje pliku $1, a nie zwykłego pliku lub nie możemy do niego czytać/zapisywać."
fi

Uruchomimy skrypt na pliku, który należy do nas i do root .

 ./script5.sh .bashrc
 ./script5.sh /etc/fstab 

script5.sh sprawdzanie, czy plik istnieje i czy są ustawione prawa do odczytu i zapisu

Aby sprawdzić istnienie katalogu, użyj testu -d . To jest „script6.sh”. Jest to część skryptu kopii zapasowej. Pierwszą rzeczą, jaką robi, jest sprawdzenie, czy katalog podany w wierszu poleceń istnieje, czy nie. Używa logicznego operatora NOT ! w teście instrukcji if .

 #!/kosz/bash

jeśli [[ ! -d $1 ]]
następnie
  echo "Tworzenie katalogu kopii zapasowej:" $1
  mkdir $1

  jeśli [[ ! $? -równ 0 ]]
  następnie
    echo "Nie udało się utworzyć katalogu kopii zapasowej:" $1
    Wyjście
  fi
w przeciwnym razie
  echo "Katalog kopii zapasowej istnieje."
fi

# kontynuuj tworzenie kopii zapasowej pliku
echo "Tworzenie kopii zapasowej do: "$1

Jeśli katalog nie istnieje, tworzy go. Jeśli pliki tworzenia katalogu, skrypt kończy działanie. Jeśli utworzenie katalogu powiedzie się lub katalog już istnieje, skrypt kontynuuje wykonywanie operacji tworzenia kopii zapasowych.

Uruchomimy skrypt, a następnie za pomocą ls i opcji -d (katalog) sprawdzimy, czy istnieje katalog kopii zapasowej.

 ./script6.sh Dokumenty/kopia zapasowa projektu
 ls -d Dokumenty/kopia zapasowa projektu 

script6.sh wykrywający, czy katalog istnieje

Katalog kopii zapasowej został utworzony. Jeśli ponownie uruchomimy skrypt, powinien zgłosić, że katalog jest już obecny.

 ./skrypt6.sh 

script6.sh ponownie wykorzystuje istniejący katalog

Skrypt odnajduje katalog i przechodzi do wykonania kopii zapasowej.

Testuj, nie zakładaj

Wcześniej czy później założenia doprowadzą do złych rzeczy. Najpierw przetestuj i odpowiednio zareaguj.

Wiedza to potęga. Użyj testów, aby dać skryptom wiedzę, której potrzebują.

POWIĄZANE: Jak pozwolić skryptom Linuksa wykryć, że działają w maszynach wirtualnych?