Hvordan gjøre noe betinget hvis en kommando lyktes eller mislyktes

Hvordan kan jeg gjøre noe slikt i bash?

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

Svar

Hvordan gjøre noe betinget hvis en kommando lyktes eller mislyktes

Det er nøyaktig hva bash «s if uttalelse gjør:

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

Legger til informasjon fra kommentarer: du don» t trenger å bruke [] syntaksen i dette tilfellet. [ er i seg selv en kommando, nesten tilsvarer test. Det er sannsynligvis den vanligste kommandoen å bruke i en if, som kan føre til antagelsen om at det er en del av skallets syntaks. Men hvis du vil teste om en kommando lyktes eller ikke, bruk selve kommandoen direkte med if, som vist ovenfor.

Kommentarer

  • Merk at semikolonet er viktig.
  • Eller du kan bare sette then på en egen linje.
  • @Joe: Jeg tror du mener if ! command ; then ... ; fi. [ er i seg selv en kommando, og det ‘ er ikke nødvendig i dette tilfellet.
  • @Joe: Min måte har også dyden til å være riktig. if [ ! command ] utfører ‘ t command; den behandler command som en streng og behandler den som sant fordi den har en lengde som ikke er null. [ er et synonym for test -kommandoen
  • Beklager. Du ‘ stemmer.

Svar

For små ting at du vil skje hvis en shell-kommando fungerer, kan du bruke && -konstruksjonen:

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

Tilsvarende for små ting som du vil skal skje når en shell-kommando mislykkes, kan du bruke ||:

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

Eller begge deler

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

Det er sannsynligvis uklokt å gjøre veldig mye med disse konstruksjonene, men de kan av og til gjøre strømmen av kontroll mye tydeligere.

Kommentarer

  • De er kortere og (i det minste i noen skall) raskere. Jeg grøsser med å huske et monster Ultrix installasjonsskript skrevet med bare disse betingede konstruksjonene jeg en gang prøvde dechiffrere …

Svar

Sjekk verdien på $?, som inneholder resultatet av å utføre den nyeste kommandoen / funksjonen:

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

Kommentarer

  • Selv om det er teknisk riktig (og dermed ikke garanterer en nedstemning), er det ‘ bruker ikke Bash ‘ s if idiom. Jeg foretrekker Keith Thompson ‘ s svar.
  • Det er fordeler med dette uttrykket – det bevarer returverdien. I det hele tatt synes jeg denne er kraftigere, men mer detaljert. det ‘ er også lettere å lese.
  • Hva er » Bash ‘ s if idiom «?
  • @Nowaker Det faktum at det eneste formålet med if er å gjøre dette. Flytkontrollforholdene i Bash undersøker alle $? bak kulissene; at ‘ er hva de gjør. Eksplisitt å undersøke verdien bør være unødvendig i de aller fleste tilfeller, og er vanligvis et nybegynnermotiv.
  • Jeg foretrekker dette for lesbarhet. Hovedkommandoen er vanligvis veldig lang. Å plassere den i en » hvis » utsagn gir dårlig lesbarhet.

Svar

Dette fungerte for meg:

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

hvis command lykkes, så blir echo "OK" utført, og siden den lykkes, stopper utførelsen der. Ellers hoppes && over, og echo "NOK" kjøres.

Kommentarer

  • Hvis du vil gjøre noe hvis det mislykkes, og bevare utgangskoden (for å vise i ledeteksten eller teste i et skript), kan du gjøre dette: command && echo "OK" || c=$?; echo "NOK"; $(exit $c)
  • @ Sam-Hasler: shouldn ‘ t that be command && echo "OK" || (c=$?; echo "NOK"; (exit $c))?
  • Også hvis echo "OK" delen kunne selv mislykkes, så er dette bedre: command && (echo "OK"; exit 0) || (c=$?; echo "NOK"; (exit $c))
  • @ jrw32982, Nice, jeg ‘ har brukt den tidligere konstruksjonen, men ikke sistnevnte.
  • Det virkelige svaret er i kommentarene, takk alle sammen!

Svar

Det skal bemerkes at if...then...fi og && / || type tilnærming omhandler exit status returnert med kommando vi vil teste (0 på suksess); noen kommandoer gir imidlertid ikke en exit-status som ikke er null hvis kommandoen mislyktes eller ikke kunne håndtere input. Dette betyr at den vanlige if og && / || tilnærmingene ikke vil fungere for dem bestemte kommandoer.

For eksempel, på Linux GNU file avsluttes fortsatt med 0 hvis den mottok en ikke-eksisterende fil som argument og find kunne ikke finne den angitte filbrukeren.

$ 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 

I slike tilfeller er en mulig måte vi kan håndtere situasjonen på å lese stderr / stdin meldinger, f.eks. de som returnerte med file -kommando, eller analyserte kommandoen som i find. For det formålet kan case uttalelse brukes.

$ 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 

Svar

Den mest feilutsatte jeg kunne komme på var:

  • Først får du verdien. Anta at du gjør noe sånt som:

RR=$?

Nå, for ikke bare denne situasjonen, men andre du kan møte, vurdere:

definert variabel:

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

Svar: ja

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

Svar: nei

udefinert variabel:

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

Svar: nei

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

Svar: ja

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

Svar: ja

Dette forhindrer alle slags feil.

Du er sannsynligvis klar over alle syntaksen, men her noen tips:

  • Bruk anførselstegn. Unngå at "blank" skal være nothing.
  • Den nye moderne notasjonen for variabler er ${variable}.
  • Hvis du legger til et null sammenkoblet før nummeret ditt, unngår du også «intet nummer i det hele tatt».
  • Men vent, å legge til et null gjør at tallet blir base-8. Du får en feil som:
    • value too great for base (error token is "08") for tall over 7. Det er da 10# spiller inn:
    • 10# tvinger tallet til å være base-10.

Svar

Du kan gjøre dette:

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

Kommentarer

  • Det fungerer, men er innviklet. Du ‘ kjører ping i en subshell av en subshell, blir utdata fra ping fanget med tanke på å kjøre den som en kommando. Men fordi utdataene blir omdirigert til / dev / null, vil det alltid være den tomme strengen. Så du ‘ kjører ingenting i en subshell, noe som betyr at den forrige utgangsstatusen (av subshell for kommandosubstitusjon, som er av ping), blir beholdt. Den riktige måten er åpenbart if ping ...; then her.

Svar

Som nevnt andre steder i denne tråden, svarer det opprinnelige spørsmålet i seg selv. Her er en illustrasjon som viser at if forhold også kan være nestet.

Dette eksemplet bruker if for å sjekke om en fil eksisterer, og om den er en vanlig fil. Hvis disse forholdene er oppfylte, sjekk om den har en størrelse som er større enn 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 

Kommentarer

  • Det er det svaret ditt gjør, men svaret ditt adresserer ikke spørsmålet.
  • @JeffSchaller, takk for notatet ditt. Jeg redigerte innlegget mitt for å inkludere en referanse til spørsmålet.

Svar

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

Kommentarer

Svar

Dette kan gjøres ganske enkelt på denne måten da $? gir deg statusen av siste kommando utført.

Så det kan være

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

Kommentarer

  • Nedstemme: Dette omformulerer ganske enkelt et tidligere svar som med rette har fått kritikk for å være unidiomatisk.
  • Egentlig var dette akkurat det jeg lette etter fordi jeg ‘ prøver for å gjøre » -kommandoen » mislykkes skriptet som en del av » set -e » som den ikke ‘ t hvis den ‘ er en del av if.Dette bør ikke ‘ ikke nedstemmes.

Legg igjen en kommentar

Din e-postadresse vil ikke bli publisert. Obligatoriske felt er merket med *