Hur kan jag göra något liknande i bash?
if "`command` returns any error"; then echo "Returned an error" else echo "Proceed..." fi
Svar
Hur man vill göra något om ett kommando lyckades eller misslyckades
Det är exakt vad bash ”s if
uttalande gör:
if command ; then echo "Command succeeded" else echo "Command failed" fi
Lägga till information från kommentarer: du don” t behöver använda [
… ]
syntax i detta fall. [
är i sig ett kommando, nästan lika med test
. Det är förmodligen det vanligaste kommandot att använda i en if
, till antagandet att det är en del av skalets syntax. Men om du vill testa om ett kommando lyckades eller inte, använd själva kommandot direkt med if
, som visas ovan.
Kommentarer
Svar
För små saker att du vill hända om ett skalkommando fungerar kan du använda &&
-konstruktionen:
rm -rf somedir && trace_output "Removed the directory"
På samma sätt för små saker som du vill ska hända när ett skalkommando misslyckas kan du använda ||
:
rm -rf somedir || exit_on_error "Failed to remove the directory"
Eller båda
rm -rf somedir && trace_output "Removed the directory" || exit_on_error "Failed to remove the directory"
Det är förmodligen oklokt att göra mycket med dessa konstruktioner, men de kan ibland göra kontrollflödet mycket tydligare.
Kommentarer
- De är kortare och (åtminstone i vissa skal) snabbare. Jag ryser ihåg ett monster Ultrix installationsskript skrivet med just dessa villkorliga konstruktioner som jag en gång försökte dechiffrera …
Svar
Kontrollera värdet på $?
, som innehåller resultatet av det senaste kommandot / funktionen:
#!/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
- Även om det är tekniskt korrekt (och därmed inte motiverar en nedröstning), ’ använder inte Bash ’ s
if
idiom. Jag föredrar Keith Thompson ’ s svar. - Det finns fördelar med detta uttryck – det bevarar returvärdet. Sammantaget tycker jag att den här är mer kraftfull, även om den är mer detaljerad. det ’ är också lättare att läsa.
- Vad är ” Bash ’ s if idiom ”?
- @Nowaker Det faktum att det enda syftet med
if
är att göra detta. Flödeskontrollförhållandena i Bash undersöker alla$?
bakom kulisserna; att ’ är vad de gör. Att uttryckligen undersöka dess värde borde vara onödigt i de allra flesta fall och är vanligtvis en nybörjare motmönster. - Jag föredrar detta för läsbarhet. Huvudkommandot är vanligtvis riktigt långt. Att placera det i ett ” om ” uttalande ger dålig läsbarhet.
Svar
Detta fungerade för mig:
command && echo "OK" || echo "NOK"
om command
lyckas, så körs echo "OK"
, och eftersom det lyckas slutar exekveringen där. Annars hoppas &&
och echo "NOK"
körs.
Kommentarer
- Om du vill göra något om det misslyckas och bevara utgångskoden (för att visas i kommandotolken eller testa i ett skript) kan du göra detta:
command && echo "OK" || c=$?; echo "NOK"; $(exit $c)
- @ Sam-Hasler: ska inte ’ t that be
command && echo "OK" || (c=$?; echo "NOK"; (exit $c))
? - Och om
echo "OK"
-delen kunde själv misslyckas, då är det bättre:command && (echo "OK"; exit 0) || (c=$?; echo "NOK"; (exit $c))
- @ jrw32982, Trevligt, jag ’ har använt den tidigare konstruktionen, men inte det senare.
- Det riktiga svaret finns i kommentarerna, tack alla!
Svar
Det bör noteras att if...then...fi
och &&
/ ||
typ av tillvägagångssätt handlar om utgångsstatus som returneras med kommando vi vill testa (0 efter framgång); Vissa kommandon returnerar dock inte en utgångsstatus som inte är noll om kommandot misslyckades eller inte kunde hantera inmatning. Detta innebär att de vanliga if
och &&
/ ||
-inställningarna inte fungerar för dem specifika kommandon.
Till exempel, på Linux GNU file
avslutas fortfarande med 0 om den fick en icke-existerande fil som argument och find
kunde inte hitta den angivna filanvändaren.
$ 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 sådana fall är ett potentiellt sätt att hantera situationen genom att läsa stderr
/ stdin
meddelanden, t.ex. de som returnerade med file
kommando, eller analysera kommandot som i find
. För detta ändamål kan case
uttalande användas.
$ 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
Det mest felbenägna jag kunde komma på var:
- Först får du värdet. Antag att du gör något som:
RR=$?
Nu, inte bara för den här situationen, utan andra du kan möta, överväga:
definierad 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: nej
odefinierad variabel:
$ AA=1 ; if (( "10#0${BB}" == 1 )) ; then echo yes ; else echo no ; fi
Svar: nej
$ 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
Detta förhindrar alla slags off-fel.
Du är nog medveten om all syntax, men här några tips:
- Använd citat. Undvik att
"blank"
ska varanothing
. - Den nya moderna notationen för variabler är
${variable}
. - Att lägga till en noll sammanfogad före ditt nummer undviker också ”inget nummer alls”.
- Men vänta, lägg till en noll gör att numret blir
base-8
. Du får ett fel som:-
value too great for base (error token is "08")
för siffror över7
. Det är då10#
spelar in: -
10#
tvingar talet att varabase-10
.
-
Svar
Du kan göra detta:
if ($( ping 4.4.4.4 -c1 > /dev/null )) ; then echo "ping response succsess!!!" fi
Kommentarer
- Det fungerar men är invecklat. Du ’ kör ping i en subshell av en subshell, utdata från
ping
fångas för att köra den som ett kommando. Men eftersom utdata omdirigeras till / dev / null kommer det alltid att vara den tomma strängen. Så du ’ kör inget i en subshell, vilket innebär att den tidigare utgångsstatusen (för subshell för kommandosubstitution, det vill säga ping) kommer att behållas. Självklart är rätt sättif ping ...; then
här.
Svar
Som nämnts någon annanstans i denna tråd svarar den ursprungliga frågan i princip på sig själv. Här är en illustration som visar att if
villkor också kan vara kapslade.
Detta exempel använder if
för att kontrollera om en fil finns och om det är en vanlig fil. Om dessa villkor är sanna, kontrollera om den har en storlek som är större än 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 är vad ditt svar gör, men ditt svar tar inte upp frågan.
- @JeffSchaller, tack för din anteckning. Jag redigerade mitt inlägg för att inkludera en hänvisning till frågan.
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
- Detta ser ganska ut som befintligt accepterat svar ; snälla attribut arbeta dig ’ återanvända, eller lägg till din egen ansträngning i dina svar.
Svar
Detta kan göras helt enkelt på det här sättet eftersom $?
ger dig status av det senaste kommandot som kördes.
Så det kan vara
#!/bin/sh ... some command ... if [ $? == 0 ] ; then echo "<the output message you want to display>" else echo "<failure message>" fi
Kommentarer
- Downvote: Detta omformar helt enkelt ett tidigare svar som med rätta har fått kritik för att vara unidiomatiskt.
- Egentligen var det precis det jag letade efter eftersom jag ’ försöker för att göra ” -kommandot ” misslyckas manuset som en del av ” set -e ” som den inte ’ t om den ’ är en del av if.Detta ska inte ’ nedröstas.
then
på en separat rad.if ! command ; then ... ; fi
.[
är i sig ett kommando, och det ’ behövs inte i det här fallet.if [ ! command ]
’ t körcommand
; det behandlarcommand
som en sträng och behandlar det som sant eftersom det har en längd som inte är noll.[
är en synonym för kommandottest