Tryb nocny
Instrukcje warunkowe – Tworzenie skryptów Bash, krok po kroku.
Instrukcje warunkowe, czyli element inteligencji w naszym skrypcie. Pozwólmy skryptowi podejmować własne decyzje!
Składnia instrukcji warunkowych w powłoce wiersza poleceń jest uważana przez początkujących za jedną z trudniejszych składni. My jednak pokażemy, że, pomimo nieintuicyjnej na pierwszy rzut oka składni, kryje się pod nią prostota i minimalizm.
Zanim przejdziemy do instrukcji warunkowych, poznamy koncepcję kodów powrotu.
Czym jest kod wyjścia?
Każdy program w momencie zakończenia swojego działania zwraca kod w postaci liczby. Przyjmuje się, że program, który wykonał operacje bez usterki, powinien zwrócić liczbę 0
.
W powłoce Bash każde polecenie zwraca kod wyjścia, którego wartość zależy od tego, czy wystąpił błąd. Zmienna $?
przechowuje wartość kodu powrotu poprzedniej komendy.
bash
echo Witaj świecie # Kod wyjścia: 0
echo Kod wyjścia: $?
ls /nieistniejący-plik # Kod wyjścia: 2
echo Kod wyjścia: $?
echo Witaj świecie # Kod wyjścia: 0
echo Kod wyjścia: $?
ls /nieistniejący-plik # Kod wyjścia: 2
echo Kod wyjścia: $?
Witaj świecie
Kod wyjścia: 0
ls: nie ma dostępu do '/nieistniejący-plik': Nie ma takiego pliku ani katalogu
Kod wyjścia: 2
Witaj świecie
Kod wyjścia: 0
ls: nie ma dostępu do '/nieistniejący-plik': Nie ma takiego pliku ani katalogu
Kod wyjścia: 2
Należy zwrócić uwagę na to, że wartość 0
jest wartością logiczną oznaczającą prawdę, a inne wartości oznaczające fałsz. Może to być mylące, ponieważ w wielu językach programowania jest na odwrót.
Warto skojarzyć bezbłędne wykonanie polecenia (kod 0
) z prawdą, a błędne wykonanie, z różnymi kodami. Przecież program może się zepsuć na wiele sposobów, dlatego też może istnieć wiele kodów powrotu dla informacji o niepowodzeniu.
bash
true # Kod wyjścia: 0
echo Kod wyjścia: $?
false # Kod wyjścia: 1
echo Kod wyjścia: $?
true # Kod wyjścia: 0
echo Kod wyjścia: $?
false # Kod wyjścia: 1
echo Kod wyjścia: $?
Kod wyjścia: 0
Kod wyjścia: 1
Kod wyjścia: 0
Kod wyjścia: 1
Operatory logiczne
W powłoce Bash operatory logiczne łączą ze sobą polecenia. Są one najczęściej używane, aby doprowadzić wiele warunków do jednego, albo aby sterować wykonywaniem komend według logicznego ciągu.
To oznacza, że można na przykład wykonać pewną komendę, pod warunkiem, że poprzednia komenda zwróciła prawdę, to jest kod 0
.
Operator logiczny | Nazwa | Opis |
---|---|---|
&& | i | Jeżeli komenda po lewej zwróci kod 0 , wykonaj komendę po prawej i zwróć kod wyjścia komendy po prawej |
|| | lub | Jeżeli komenda po lewej zwróci kod 0 , zwróć kod wyjścia 0 . W przeciwnym wypadku wykonaj komendę po prawej i zwróć jej kod wyjścia |
bash
gcc -o program main.c && ./program
gcc -o program main.c && ./program
Powyższy przykład uruchomi program ./program
pod warunkiem, że jego kompilacja z kodu źródłowego zakończyła się sukcesem.
Polecenie if
Wyrażenie warunkowe if
wykonuje zestaw komend, jeżeli warunek zwróci kod błędu równy 0
.
bash
if warunek; then
# Zestaw komend, które wykonają się
# jeżeli warunek zwrócił kod 0
echo Prawda
fi
if warunek; then
# Zestaw komend, które wykonają się
# jeżeli warunek zwrócił kod 0
echo Prawda
fi
W miejsce warunku można wstawić dowolne polecenie Basha.
Wyrażenie warunkowe w formie zaprezentowanej powyżej pozwala sprawdzić, czy dane polecenie wykonało się poprawnie i wykonać w takim przypadku odpowiednie operacje.
bash
#!/usr/bin/env bash
echo Tworzenie katalogu ~/Parzychedu
if mkdir ~/Parzychedu; then
echo Katalog utworzony pomyślnie.
fi
#!/usr/bin/env bash
echo Tworzenie katalogu ~/Parzychedu
if mkdir ~/Parzychedu; then
echo Katalog utworzony pomyślnie.
fi
Tworzenie katalogu ~/Parzychedu
Katalog utworzony pomyślnie
Tworzenie katalogu ~/Parzychedu
Katalog utworzony pomyślnie
Tworzenie katalogu ~/Parzychedu
mkdir: nie można utworzyć katalogu „/home/jacek/Parzychedu”: Plik istnieje
Tworzenie katalogu ~/Parzychedu
mkdir: nie można utworzyć katalogu „/home/jacek/Parzychedu”: Plik istnieje
W przypadku A, nasz skrypt został wywołany w momencie, w którym katalog ~/Parzychedu nie istniał. W trakcie wykonywania skryptu została wykonana komenda mkdir ~/Parzychedu
, która utworzyła katalog, i w związku z tym zwróciła kod 0
, oznaczający sukces. Ponieważ ta komenda jest warunkiem dla wyrażenia if, i zwróciła wartość prawdy (0
), została wykonana komenda echo Katalog utworzony pomyślnie
z bloku wewnętrznego.
W przypadku B, katalog ~/Parzychedu został uprzednio utworzony. Nie wywołał się blok komend wewnątrz wyrażenia warunkowego, ponieważ komenda mkdir
zwróciła kod różny od 0
.
Warto zauważyć, że wyjście polecenia warunkowego nie jest w żaden sposób ukryte. Jest ono traktowane tak, jak każde inne polecenie, przy czym jego kod wyjścia decyduje o wykonaniu konkretnego bloku kodu.
Wykonaj, jeżeli nie prawda
Kiedy chcemy sprawdzić, czy komenda zwróciła fałsz, przyda się polecenie !
. Wykonuje ono komendę podaną w miejsce argumentów i odwraca kod wyjścia, w taki sposób, że prawda staje się fałszem, a fałsz prawdą. Inaczej, kod różny od 0
staje się zerem, a kod 0
zostaje przekształcony w 1
.
bash
#!/usr/bin/env bash
echo Aktualizowanie systemu
if ! sudo apt -y update; then
echo Nie udało się zaaktualizować repozytoriów oprogramowania.
echo Wychodzę ze skryptu.
exit 1
fi
if ! sudo apt -y dist-upgrade; then
echo Nie udało się zaaktualizować oprogramowania systemu.
echo Wychodzę ze skryptu.
exit 1
fi
echo Zaaktualizowano w pełni system
#!/usr/bin/env bash
echo Aktualizowanie systemu
if ! sudo apt -y update; then
echo Nie udało się zaaktualizować repozytoriów oprogramowania.
echo Wychodzę ze skryptu.
exit 1
fi
if ! sudo apt -y dist-upgrade; then
echo Nie udało się zaaktualizować oprogramowania systemu.
echo Wychodzę ze skryptu.
exit 1
fi
echo Zaaktualizowano w pełni system
Aktualizowanie systemu
<ta część wyjścia została przycięta dla czytelności>
Zaaktualizowano w pełni system
Aktualizowanie systemu
<ta część wyjścia została przycięta dla czytelności>
Zaaktualizowano w pełni system
Aktualizowanie systemu
[sudo] password for jacek:
sudo: 1 incorrect password attempt
Nie udało się zaaktualizować repozytoriów oprogramowania.
Wychodzę ze skryptu.
Aktualizowanie systemu
[sudo] password for jacek:
sudo: 1 incorrect password attempt
Nie udało się zaaktualizować repozytoriów oprogramowania.
Wychodzę ze skryptu.
Powyższy skrypt zaktualizuje oprogramowanie systemu opartego na dystrybucjach Debian albo Ubuntu.
Ta część strony została oznaczona, jakoby była w trakcie konstrukcji. To oznacza, że treść w miejscu tego komunikatu zostanie uzupełniona w najbliższym czasie.
Komenda test
jako narzędzie sprawdzające
Komenda test
potrafi między innymi wykonywać operacje sprawdzające na zmiennej, porównywać zmienne, sprawdzać stan plików. Łatwo jest przewidzieć, że będziemy często używać tej komendy jako warunku polecenia if
.
bash
test "napis1" = "napis2" # Kod wyjścia: 1
echo Czy napisy są równe? Wynik: $?
test "napis" = "napis" # Kod wyjścia: 0
echo Czy napisy są równe? Wynik: $?
test "napis1" = "napis2" # Kod wyjścia: 1
echo Czy napisy są równe? Wynik: $?
test "napis" = "napis" # Kod wyjścia: 0
echo Czy napisy są równe? Wynik: $?
bash
Czy napisy są równe? Wynik: 1
Czy napisy są równe? Wynik: 0
Czy napisy są równe? Wynik: 1
Czy napisy są równe? Wynik: 0
Ta część strony została oznaczona, jakoby była w trakcie konstrukcji. To oznacza, że treść w miejscu tego komunikatu zostanie uzupełniona w najbliższym czasie.
Polecenie test
spotykamy najczęściej w skróconej formie.
bash
[ "napis1" = "napis2" ] # Kod wyjścia: 1
echo Czy napisy są równe? Wynik: $?
[ "napis" = "napis" ] # Kod wyjścia: 0
echo Czy napisy są równe? Wynik: $?
[ "napis1" = "napis2" ] # Kod wyjścia: 1
echo Czy napisy są równe? Wynik: $?
[ "napis" = "napis" ] # Kod wyjścia: 0
echo Czy napisy są równe? Wynik: $?
bash
Czy napisy są równe? Wynik: 1
Czy napisy są równe? Wynik: 0
Czy napisy są równe? Wynik: 1
Czy napisy są równe? Wynik: 0
Działanie powyższych poleceń jest analogiczne do poprzednich.
Polecenie test wewnątrz instrukcji warunkowej
bash
#!/usr/bin/env bash
if [ "$USER" = "root" ]; then
echo Skrypt został uruchomiony przez użytkownika root.
else
echo Skrypt został uruchomiony przez użytkownika innego niż root.
fi
#!/usr/bin/env bash
if [ "$USER" = "root" ]; then
echo Skrypt został uruchomiony przez użytkownika root.
else
echo Skrypt został uruchomiony przez użytkownika innego niż root.
fi
Wywołując powyższy skrypt, możemy otrzymać dwie możliwości.
bash
bash skrypt.sh
bash skrypt.sh
Skrypt został uruchomiony przez użytkownika innego niż root.
Skrypt został uruchomiony przez użytkownika innego niż root.
bash
sudo bash skrypt.sh
sudo bash skrypt.sh
Skrypt został uruchomiony przez użytkownika root.
Skrypt został uruchomiony przez użytkownika root.
Ta część strony została oznaczona, jakoby była w trakcie konstrukcji. To oznacza, że treść w miejscu tego komunikatu zostanie uzupełniona w najbliższym czasie.
Składnia komendy test
porównująca ze sobą dwie frazy
Ta część strony została oznaczona, jakoby była w trakcie konstrukcji. To oznacza, że treść w miejscu tego komunikatu zostanie uzupełniona w najbliższym czasie.
test fraza1 operatorPorównania fraza2
Operator porównania | Warunek |
---|---|
-eq | Liczba równa drugiej |
-lt | Liczba mniejsza od drugiej |
-le | Liczba mniejsza od drugiej, lub równa drugiej |
-gt | Liczba większa od drugiej |
-ge | Liczba większa od drugiej, lub równa drugiej |
= | Napis równoważny drugiemu |
Składnia komenty test
sprawdzająca jedną frazę
Ta część strony została oznaczona, jakoby była w trakcie konstrukcji. To oznacza, że treść w miejscu tego komunikatu zostanie uzupełniona w najbliższym czasie.
test operatorWarunku fraza
Operator warunku | Warunek |
---|---|
-z | Napis jest pusty |
-e | Ścieżka istnieje |
-d | Katalog istnieje |
-f | Plik istnieje |
-L | Dowiązanie symboliczne istnieje |
Przykłady skryptów wykorzystujących instrukcje warunkowe
Ta część strony została oznaczona, jakoby była w trakcie konstrukcji. To oznacza, że treść w miejscu tego komunikatu zostanie uzupełniona w najbliższym czasie.