Skip to content
Na tej stronie

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 logicznyNazwaOpis
&&iJeżeli komenda po lewej zwróci kod 0, wykonaj komendę po prawej i zwróć kod wyjścia komendy po prawej
||lubJeż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  równe? Wynik: $?
test "napis" = "napis" # Kod wyjścia: 0
echo Czy napisy  równe? Wynik: $?
test "napis1" = "napis2" # Kod wyjścia: 1
echo Czy napisy  równe? Wynik: $?
test "napis" = "napis" # Kod wyjścia: 0
echo Czy napisy  równe? Wynik: $?
bash
Czy napisy  równe? Wynik: 1
Czy napisy  równe? Wynik: 0
Czy napisy  równe? Wynik: 1
Czy napisy  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  równe? Wynik: $?
[ "napis" = "napis" ] # Kod wyjścia: 0
echo Czy napisy  równe? Wynik: $?
[ "napis1" = "napis2" ] # Kod wyjścia: 1
echo Czy napisy  równe? Wynik: $?
[ "napis" = "napis" ] # Kod wyjścia: 0
echo Czy napisy  równe? Wynik: $?
bash
Czy napisy  równe? Wynik: 1
Czy napisy  równe? Wynik: 0
Czy napisy  równe? Wynik: 1
Czy napisy  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ównaniaWarunek
-eqLiczba równa drugiej
-ltLiczba mniejsza od drugiej
-leLiczba mniejsza od drugiej, lub równa drugiej
-gtLiczba większa od drugiej
-geLiczba 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 warunkuWarunek
-zNapis jest pusty
-eŚcieżka istnieje
-dKatalog istnieje
-fPlik istnieje
-LDowią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.