Jak mogę zrobić coś takiego w bashu?
if "`command` returns any error"; then echo "Returned an error" else echo "Proceed..." fi
Odpowiedź
Jak warunkowo coś zrobić, jeśli polecenie zakończyło się powodzeniem lub niepowodzeniem
To jest dokładnie to, co bash Instrukcja „s if
powoduje:
if command ; then echo "Command succeeded" else echo "Command failed" fi
Dodawanie informacji z komentarzy: nie” t w tym przypadku należy użyć składni [
… ]
. [
samo w sobie jest poleceniem, bardzo zbliżonym do test
. Jest to prawdopodobnie najczęściej używane polecenie w if
, które może prowadzić do założenia, że jest to część składni powłoki. Ale jeśli chcesz sprawdzić, czy polecenie się powiodło, czy nie, użyj samego polecenia bezpośrednio z if
, jak pokazano powyżej.
Komentarze
Odpowiedź
Małe rzeczy co ma się wydarzyć, jeśli polecenie powłoki działa, możesz użyć konstrukcji &&
:
rm -rf somedir && trace_output "Removed the directory"
Podobnie małe rzeczy, które mają się wydarzyć, gdy polecenie powłoki się nie powiedzie, możesz użyć ||
:
rm -rf somedir || exit_on_error "Failed to remove the directory"
Lub obu
rm -rf somedir && trace_output "Removed the directory" || exit_on_error "Failed to remove the directory"
Prawdopodobnie nierozsądne jest robić wiele z tymi konstrukcjami, ale czasami mogą one znacznie zwiększyć przejrzystość sterowania.
Komentarze
- Są krótsze i (przynajmniej w niektórych muszlach) szybsze. Wzdrygam się przypominając sobie potworny skrypt instalacyjny Ultrix napisany tylko z tych warunkowych konstrukcji, które kiedyś próbowałem rozszyfrować …
Odpowiedź
Sprawdź wartość $?
, który zawiera wynik wykonania ostatniego polecenia / funkcji:
#!/bin/bash echo "this will work" RESULT=$? if [ $RESULT -eq 0 ]; then echo success else echo failed fi if [ $RESULT == 0 ]; then echo success 2 else echo failed 2 fi
Komentarze
- Chociaż technicznie poprawne (a więc nie gwarantuje negatywnego głosu), nie używa idiomu Bash ' s
if
. Wolę odpowiedź Keitha Thompsona '. - Ten idiom ma zalety – zachowuje zwracaną wartość. W sumie uważam, że ten jest potężniejszy, choć bardziej szczegółowy. ' jest również bardziej czytelny.
- Co to jest ” Bash ' s if idiom „?
- @Nowaker Fakt, że jedynym celem
if
jest zrobienie to. Wszystkie warunki kontroli przepływu w Bashu sprawdzają$?
za kulisami; że ' jest tym, co robią. Wyraźne badanie jego wartości powinno być niepotrzebne w większości przypadków i jest to zazwyczaj początkujący antywzor. - Wolę to ze względu na czytelność. Główne polecenie jest zazwyczaj bardzo długie. Umieszczenie go w instrukcji „, jeśli ” powoduje słabą czytelność.
Odpowiedź
U mnie zadziałało:
command && echo "OK" || echo "NOK"
if command
powiedzie się, a następnie echo "OK"
jest wykonywane, a ponieważ się powiodło, wykonywanie zostaje zatrzymane. W przeciwnym razie &&
jest pomijane, a echo "NOK"
jest wykonywany.
Komentarze
- Jeśli chcesz coś zrobić, jeśli to się nie powiedzie, zachowaj kod zakończenia (do wyświetlenia w wierszu polecenia lub do przetestowania w skrypcie), możesz to zrobić:
command && echo "OK" || c=$?; echo "NOK"; $(exit $c)
- @ Sam-Hasler: shouldn ' t, który jest
command && echo "OK" || (c=$?; echo "NOK"; (exit $c))
? - Ponadto, jeśli
echo "OK"
część może sama niepowodzenie, to jest lepiej:command && (echo "OK"; exit 0) || (c=$?; echo "NOK"; (exit $c))
- @ jrw32982, Dobrze, ' użyłem poprzedniej konstrukcji, ale nie to drugie.
- Prawdziwa odpowiedź znajduje się w komentarzach, dzięki wszystkim!
Odpowiedź
Należy zauważyć, że if...then...fi
i &&
/ ||
rodzaj podejścia dotyczy statusu wyjścia zwróconego przez polecenie, które chcemy przetestować (0 w przypadku sukcesu); jednak niektóre polecenia nie zwracają niezerowego kodu wyjścia, jeśli polecenie zawiodło lub nie radzi sobie z danymi wejściowymi. Oznacza to, że zwykłe metody if
i &&
/ ||
nie zadziałają w przypadku tych konkretnych poleceń.
Na przykład w systemie Linux GNU file
nadal kończy się z 0, jeśli jako argument otrzymał nieistniejący plik i find
nie można znaleźć pliku określonego przez użytkownika.
$ find . -name "not_existing_file" $ echo $? 0 $ file ./not_existing_file ./not_existing_file: cannot open `./not_existing_file" (No such file or directory) $ echo $? 0
W takich przypadkach jednym z potencjalnych sposobów rozwiązania problemu jest przeczytanie stderr
/ stdin
wiadomości, np. te, które zwróciły polecenie file
, lub przeanalizują dane wyjściowe polecenia, jak w przypadku find
. W tym celu można użyć instrukcji case
.
$ file ./doesntexist | while IFS= read -r output; do > case "$output" in > *"No such file or directory"*) printf "%s\n" "This will show up if failed";; > *) printf "%s\n" "This will show up if succeeded" ;; > esac > done This will show up if failed $ find . -name "doesn"texist" | if ! read IFS= out; then echo "File not found"; fi File not found
Odpowiedź
Najbardziej podatna na błędy, jaką mogłem wymyślić, to:
- Najpierw pobierz wartość. Załóżmy, że robisz coś takiego:
RR=$?
Nie tylko w tej sytuacji, ale także w innych, z którymi możesz się spotkać, rozważ:
zdefiniowana zmienna:
$ AA=1 ; if (( "10#0${AA}" == 1 )) ; then echo yes ; else echo no ; fi
Odpowiedź: tak
$ AA=1 ; if (( "10#0${AA}" != 1 )) ; then echo yes ; else echo no ; fi
Odpowiedź: nie
niezdefiniowana zmienna:
$ AA=1 ; if (( "10#0${BB}" == 1 )) ; then echo yes ; else echo no ; fi
Odpowiedź: nie
$ AA=1 ; if (( "10#0${BB}" != 1 )) ; then echo yes ; else echo no ; fi
Odpowiedź: tak
$ AA=1 ; if (( "10#0${BB}" == 0 )) ; then echo yes ; else echo no ; fi
Odpowiedź: tak
Zapobiega to wszelkiego rodzaju błędom.
Prawdopodobnie znasz całą składnię, ale tutaj niektóre wskazówki:
- Używaj cudzysłowów. Unikaj
"blank"
bycianothing
. - Nowa nowoczesna notacja dla zmiennych to
${variable}
. - Dodanie zera połączonego przed liczbą również pozwala uniknąć „żadnego numeru”.
- Ale poczekaj, dodanie zera powoduje, że liczba staje się
base-8
. Pojawi się błąd taki jak:-
value too great for base (error token is "08")
dla liczb powyżej7
. To wtedy pojawia się10#
: -
10#
wymuszabase-10
.
-
Odpowiedź
Możesz to zrobić:
if ($( ping 4.4.4.4 -c1 > /dev/null )) ; then echo "ping response succsess!!!" fi
Komentarze
- To działa, ale jest skomplikowane. Gdy ' wykonujesz polecenie ping w podpowłoce podpowłoki, dane wyjściowe
ping
są przechwytywane w celu uruchomienia go jako polecenia. Ale ponieważ dane wyjściowe są przekierowywane do / dev / null, zawsze będzie to pusty ciąg. Więc ' nie uruchamiasz niczego w podpowłoce, co oznacza, że poprzedni stan wyjścia (podpowłoki zastępującej polecenia, czyli ping) zostanie zachowany. Oczywiście prawidłowy sposób jestif ping ...; then
tutaj.
Odpowiedź
Jak zauważono w innym miejscu tego wątku, pierwotne pytanie w zasadzie odpowiada samo sobie. Oto ilustracja pokazująca, że warunki if
również mogą być zagnieżdżone.
W tym przykładzie if
sprawdza, czy plik istnieje i czy jest zwykłym plikiem. Jeśli te warunki są spełnione, sprawdź, czy ma rozmiar większy niż 0.
#!/bin/bash echo "Which error log are you checking today? " read answer if [ -f /opt/logs/$answer*.errors ] then if [ -s /opt/logs/$answer*.errors ] then echo "Content is present in the $answer error log file." else echo "No errors are present in the $answer error log file." fi else echo "$answer does not have an error log at this time." fi
Komentarze
- Tak właśnie działa Twoja odpowiedź, ale Twoja odpowiedź nie odpowiada na pytanie.
- @JeffSchaller, dziękuję za uwagę. Zmieniłem post, aby zawierał odniesienie do pytania.
Odpowiedź
#!/bin/bash if command-1 ; then echo "command-1 succeeded and now running from this block command-2" command-2 else echo "command-1 failed and now running from this block command-3" command-3 fi
Komentarze
- Wygląda to trochę jak istniejąca zaakceptowana odpowiedź ; atrybut pracuj nad ' ponownym użyciem lub dodaj własny wysiłek do swoich odpowiedzi.
Odpowiedź
Można to zrobić w ten sposób, ponieważ $?
podaje stan ostatniego wykonanego polecenia.
Więc mogłoby być
#!/bin/sh ... some command ... if [ $? == 0 ] ; then echo "<the output message you want to display>" else echo "<failure message>" fi
Komentarze
- Głos przeciw: to po prostu parafraza wcześniejszą odpowiedź, która została słusznie skrytykowana za bycie jednostronnym.
- Właściwie to właśnie tego szukałem, ponieważ ' próbuję aby polecenie ” ” zakończyło się niepowodzeniem skryptu jako część ” set -e ” co nie ' t, jeśli ' jest częścią if.Nie powinno to ' być odrzuconym.
then
w osobnym wierszu.if ! command ; then ... ; fi
.[
jest samo w sobie poleceniem i ' nie jest w tym przypadku potrzebne.if [ ! command ]
nie ' nie wykonujecommand
; traktujecommand
jako ciąg i traktuje go jako prawdę, ponieważ ma niezerową długość.[
jest synonimem poleceniatest