Cum se face ceva condiționat dacă o comandă a reușit sau a eșuat

Cum pot face așa ceva în bash?

if "`command` returns any error"; then echo "Returned an error" else echo "Proceed..." fi 

Răspuns

Cum se face ceva condiționat dacă o comandă a reușit sau a eșuat

Exact ceea ce este bash Declarația „s if face:

if command ; then echo "Command succeeded" else echo "Command failed" fi 

Adăugarea de informații din comentarii: trebuie să utilizați sintaxa [] în acest caz. [ este în sine o comandă, foarte aproape echivalentă cu test. Este probabil cea mai comună comandă de utilizat într-un if, care poate conduce la presupunerea că face parte din sintaxa shell-ului. Dar dacă doriți să testați dacă o comandă a reușit sau nu, utilizați comanda în sine direct cu if, așa cum se arată mai sus.

Comentarii

  • Rețineți că punctul și virgula este important.
  • Sau pur și simplu puteți pune then pe o linie separată.
  • @Joe: cred că vrei să spui if ! command ; then ... ; fi. [ este ea însăși o comandă și ‘ nu este necesară în acest caz.
  • @Joe: Drumul meu are și virtutea de a fi corect. if [ ! command ] nu ‘ nu execută command tratează command ca un șir și îl tratează ca fiind adevărat deoarece are o lungime diferită de zero. [ este un sinonim pentru comanda test
  • Hopa. ‘ ești corect.

Răspunde

Pentru lucruri mici că doriți să se întâmple dacă o comandă shell funcționează, puteți utiliza construcția &&:

rm -rf somedir && trace_output "Removed the directory" 

Similar pentru lucruri mici pe care doriți să se întâmple atunci când o comandă shell eșuează, puteți utiliza ||:

rm -rf somedir || exit_on_error "Failed to remove the directory" 

Sau ambele

rm -rf somedir && trace_output "Removed the directory" || exit_on_error "Failed to remove the directory" 

Probabil nu este înțelept să faci foarte multe lucruri cu aceste construcții, dar uneori pot face fluxul de control mult mai clar.

Comentarii

  • Acestea sunt mai scurte și (cel puțin în unele shell-uri) mai rapide. Mă înfricoșez amintindu-mi un script de instalare monstru Ultrix scris doar cu aceste construcții condiționale pe care am încercat odată descifrează …

Răspunde

Verifică valoarea $?, care conține rezultatul executării celei mai recente comenzi / funcții:

#!/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 

Comentarii

  • Deși este corect din punct de vedere tehnic (și, prin urmare, nu justifică o vot negativ), acesta „6d73376bee”>

nu folosește expresia Bash ‘ sifPrefer răspunsul lui Keith Thompson ‘.

  • Există avantaje acestui idiom – păstrează valoarea returnată. În total, consider că acesta este mai puternic, deși mai detaliat. ‘ este, de asemenea, mai ușor de citit.
  • Ce este ” Bash ‘ s if idiom „?
  • @Nowaker Faptul că singurul scop al if este de a face acest. Condițiile de control al fluxului din Bash examinează toate $? în culise; ‘ este ceea ce fac . Examinarea explicită a valorii sale ar trebui să fie inutilă în marea majoritate a cazurilor și este de obicei un antipattern pentru începători.
  • Prefer acest lucru pentru lizibilitate. Comanda principală este de obicei una foarte lungă. Punerea în interiorul unei ” dacă ” face ca lizibilitatea să fie slabă.
  • Răspuns

    Acest lucru a funcționat pentru mine:

    command && echo "OK" || echo "NOK" 

    if command reușește, apoi echo "OK" este executat și, deoarece are succes, executarea se oprește acolo. În caz contrar, && este omis și echo "NOK" este executat.

    Comentarii

    • Dacă doriți să faceți ceva dacă nu reușește și păstrați codul de ieșire (pentru a afișa în promptul de comandă sau pentru a testa într-un script), puteți face acest lucru: command && echo "OK" || c=$?; echo "NOK"; $(exit $c)
    • @ Sam-Hasler: shouldn care să fie command && echo "OK" || (c=$?; echo "NOK"; (exit $c))?
    • De asemenea, dacă partea echo "OK" ar putea fi ea însăși eșuează, atunci este mai bine: command && (echo "OK"; exit 0) || (c=$?; echo "NOK"; (exit $c))
    • @ jrw32982, Nisa, am ‘ am folosit construcția anterioară, dar nu din urmă.
    • Răspunsul real este în comentarii, mulțumesc tuturor!

    Răspuns

    Trebuie remarcat faptul că if...then...fi și && / || tip de abordare tratează starea de ieșire returnată prin comanda pe care dorim să o testăm (0 la succes); cu toate acestea, unele comenzi nu returnează o stare de ieșire diferită de zero dacă comanda a eșuat sau nu s-ar putea ocupa de intrare. Aceasta înseamnă că abordările obișnuite if și && / || nu vor funcționa pentru cei comenzi speciale.

    De exemplu, pe Linux GNU file iese încă cu 0 dacă a primit ca argument un fișier inexistent și find nu s-a putut localiza fișierul specificat de utilizator.

    $ 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 

    În astfel de cazuri, un mod potențial în care am putea rezolva situația este citind stderr / stdin mesaje, de ex. cele care au revenit prin comanda file sau analizează ieșirea comenzii ca în find. În acest scop, ar putea fi folosită declarația 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 

    Răspuns

    Cea mai predispusă eroare cu care am putut veni a fost:

    • Mai întâi, obțineți valoarea. Să presupunem că faceți ceva de genul:

    RR=$?

    Acum, nu numai pentru această situație, ci și pentru altele cu care vă puteți confrunta, ia în considerare:

    variabilă definită:

    $ AA=1 ; if (( "10#0${AA}" == 1 )) ; then echo yes ; else echo no ; fi

    Răspuns: da

    $ AA=1 ; if (( "10#0${AA}" != 1 )) ; then echo yes ; else echo no ; fi

    Răspuns: nu

    variabilă nedefinită:

    $ AA=1 ; if (( "10#0${BB}" == 1 )) ; then echo yes ; else echo no ; fi

    Răspuns: nu

    $ AA=1 ; if (( "10#0${BB}" != 1 )) ; then echo yes ; else echo no ; fi

    Răspuns: da

    $ AA=1 ; if (( "10#0${BB}" == 0 )) ; then echo yes ; else echo no ; fi

    Răspuns: da

    Acest lucru previne toate tipurile de erori.

    Probabil că sunteți conștienți de toată sintaxa, dar aici câteva sfaturi:

    • Folosiți ghilimele. Evitați ca "blank" să fie nothing.
    • Noua notație modernă pentru variabile este ${variable}.
    • Adăugarea unui zero concatenat înainte de numărul dvs. evită, de asemenea, „niciun număr”.
    • Dar așteptați, adăugarea unui zero face ca numărul să devină base-8. Veți primi o eroare de genul:
      • value too great for base (error token is "08") pentru numerele de peste 7. Atunci intră în joc 10#:
      • 10# forțează numărul să fie base-10.

    Răspuns

    Puteți face acest lucru:

    if ($( ping 4.4.4.4 -c1 > /dev/null )) ; then echo "ping response succsess!!!" fi 

    Comentarii

    • Aceasta funcționează, dar este complicată. ‘ executați ping într-un subshell al unui subshell, ieșirea ping este capturată în vederea executării acestuia ca o comandă. Dar, deoarece ieșirea este redirecționată către / dev / null, acesta va fi întotdeauna șirul gol. Deci, ‘ nu executați nimic într-un subshell, ceea ce înseamnă că starea de ieșire anterioară (a subshell-ului de substituire a comenzii, adică ping) va fi păstrată. Evident, modul corect este if ping ...; then aici.

    Răspuns

    După cum sa menționat în altă parte a acestui fir, întrebarea inițială răspunde în sine. Iată o ilustrație care arată că if pot fi, de asemenea, imbricate.

    Acest exemplu folosește if pentru a verifica dacă există un fișier și dacă este un fișier obișnuit. Dacă aceste condiții sunt adevărate, verificați dacă are sau nu o dimensiune mai mare de 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 

    Comentarii

    • Așa face răspunsul dvs., dar răspunsul dvs. nu abordează întrebarea.
    • @JeffSchaller, vă mulțumim pentru nota dvs. Mi-am editat postarea pentru a include o referință la întrebare.

    Răspuns

    #!/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 

    Comentarii

    Răspuns

    Acest lucru ar putea fi făcut pur și simplu în acest fel, deoarece $? vă oferă statutul a ultimei comenzi executate.

    Deci ar putea fi

    #!/bin/sh ... some command ... if [ $? == 0 ] ; then echo "<the output message you want to display>" else echo "<failure message>" fi 

    Comentarii

    • Vot negativ: acesta parafrazează pur și simplu un răspuns anterior care a primit pe bună dreptate critici pentru că este unidiomatic.
    • De fapt, exact asta căutam pentru că ‘ încerc pentru a face ca ” comanda ” eșuează scriptul ca parte a ” set -e ” pe care nu o face ‘ t dacă ‘ face parte din if.Acest lucru nu ar trebui ‘ să nu fie votat în jos.

    Lasă un răspuns

    Adresa ta de email nu va fi publicată. Câmpurile obligatorii sunt marcate cu *