Come fare qualcosa in modo condizionale se un comando è riuscito o meno

Come posso fare qualcosa di simile in bash?

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

Risposta

Come fare qualcosa in modo condizionale se un comando ha avuto successo o meno

Questo è esattamente ciò che bash Listruzione “s if:

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

Aggiunta di informazioni dai commenti: don” t in questo caso deve utilizzare la sintassi []. [ è esso stesso un comando, quasi equivalente a test. È probabilmente il comando più comune da utilizzare in un if, che può portare dal presupposto che fa parte della sintassi della shell. Ma se vuoi verificare se un comando è riuscito o meno, usa il comando stesso direttamente con if, come mostrato sopra.

Commenti

  • Tieni presente che il punto e virgola è importante.
  • Oppure puoi semplicemente inserire then su una riga separata.
  • @Joe: Penso che tu intenda if ! command ; then ... ; fi. [ è esso stesso un comando e ‘ non è necessario in questo caso.
  • @Joe: A modo mio ha anche la virtù di essere corretto. if [ ! command ] non ‘ t esegue command; tratta command come una stringa e lo considera vero perché ha una lunghezza diversa da zero. [ è un sinonimo del comando test
  • Ops. ‘ hai corretto.

Rispondi

Per piccole cose che vuoi che accada se un comando della shell funziona, puoi usare il && costrutto:

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

Allo stesso modo per piccole cose che vuoi che accadano quando un comando della shell fallisce, puoi usare ||:

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

O entrambi

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

Probabilmente non è saggio fare molto con questi costrutti, ma a volte possono rendere il flusso di controllo molto più chiaro.

Commenti

  • Sono più brevi e (almeno in alcune shell) più veloci. Mi vengono i brividi al ricordo di un mostruoso script di installazione di Ultrix scritto solo con queste costruzioni condizionali che una volta ho provato decifrare …

Risposta

Controlla il valore di $?, che contiene il risultato dellesecuzione del comando / funzione più recente:

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

Commenti

  • Sebbene tecnicamente corretto (e quindi non garantisce un voto negativo), ‘ non utilizza il linguaggio Bash ‘ s if. Preferisco la risposta di Keith Thompson ‘.
  • Ci sono vantaggi in questo idioma: preserva il valore restituito. In tutto, trovo che questo sia più potente, anche se più prolisso. ‘ è anche più facile da leggere.
  • Che cosè ” Bash ‘ s if idiom “?
  • @Nowaker Il fatto che lunico scopo di if è quello di fare Questo. Le condizioni di controllo del flusso in Bash esaminano tutte $? dietro le quinte; che ‘ è quello che fanno. Esaminare esplicitamente il suo valore dovrebbe essere inutile nella stragrande maggioranza dei casi e di solito è un antipattern per principianti.
  • Lo preferisco per la leggibilità. Il comando principale è in genere molto lungo. Inserendolo in unistruzione ” se ” si crea una cattiva leggibilità.

Risposta

Questo ha funzionato per me:

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

if command ha esito positivo, quindi echo "OK" viene eseguito e, poiché ha esito positivo, lesecuzione si interrompe qui. In caso contrario, && viene saltato e echo "NOK" viene eseguito.

Commenti

  • Se vuoi fare qualcosa se fallisce, e conserva il codice di uscita (da mostrare nel prompt dei comandi o da testare in uno script), puoi farlo: command && echo "OK" || c=$?; echo "NOK"; $(exit $c)
  • @ Sam-Hasler: shouldn ‘ deve essere command && echo "OK" || (c=$?; echo "NOK"; (exit $c))?
  • Inoltre, se la parte echo "OK" potesse fallire, allora è meglio: command && (echo "OK"; exit 0) || (c=$?; echo "NOK"; (exit $c))
  • @ jrw32982, Nice, I ‘ ho utilizzato la precedente costruzione, ma non questultimo.
  • La vera risposta è nei commenti, grazie a tutti!

Risposta

Va notato che if...then...fi e && / || il tipo di approccio si occupa dello stato di uscita restituito dal comando che vogliamo testare (0 in caso di successo); tuttavia, alcuni comandi non restituiscono uno stato di uscita diverso da zero se il comando fallisce o non riesce a gestire linput. Ciò significa che i soliti if e && / || non funzioneranno “per quelli comandi particolari.

Ad esempio, su Linux GNU file esce ancora con 0 se ha ricevuto un file non esistente come argomento e find Impossibile individuare il file specificato dallutente.

$ 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 

In questi casi, un possibile modo per gestire la situazione è leggere stderr / stdin messaggi, ad es. quelli restituiti dal comando file o analizzano loutput del comando come in find. A tal fine, è possibile utilizzare listruzione 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 

Risposta

Il più soggetto a errori che sono riuscito a trovare è stato:

  • Innanzitutto, ottieni il valore. Supponi di fare qualcosa del tipo:

RR=$?

Ora, non solo per questa situazione, ma anche per altre che potresti dover affrontare, considera:

variabile definita:

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

Risposta: sì

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

Risposta: no

variabile undefined:

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

Risposta: no

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

Risposta: sì

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

Risposta: sì

Questo previene tutti i tipi di errori.

Probabilmente sei a conoscenza di tutta la sintassi, ma qui alcuni suggerimenti:

  • Usa le virgolette. Evita che "blank" sia nothing.
  • La nuova notazione moderna per le variabili è ${variable}.
  • Laggiunta di uno zero concatenato prima del numero evita anche “nessun numero”.
  • Ma aspetta, laggiunta di uno zero fa diventare il numero base-8. Riceverai un errore del tipo:
    • value too great for base (error token is "08") per i numeri superiori a 7. È allora che 10# entra in gioco:
    • 10# forza il numero a essere base-10.

Risposta

Puoi farlo:

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

Commenti

  • Funziona ma è complicato. Se ‘ stai eseguendo ping in una subshell di una subshell, loutput di ping viene acquisito in vista dellesecuzione come comando. Ma poiché loutput viene reindirizzato a / dev / null, sarà sempre la stringa vuota. Quindi ‘ non stai eseguendo nulla in una subshell, il che significa che il precedente stato di uscita (della subshell di sostituzione del comando, cioè del ping) verrà mantenuto. Ovviamente, il modo corretto è if ping ...; then qui.

Risposta

Come notato altrove in questo thread, la domanda originale fondamentalmente risponde da sola. Di seguito è riportata unillustrazione che mostra che anche le condizioni if possono essere nidificate.

Questo esempio utilizza if per verificare se esiste un file e se è un file normale. Se queste condizioni sono vere, controlla se ha o meno una dimensione maggiore di 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 

Commenti

  • Questo è ciò che fa la tua risposta, ma la tua risposta non affronta la domanda.
  • @JeffSchaller, grazie per la tua nota. Ho modificato il mio post per includere un riferimento alla domanda.

Risposta

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

Commenti

Risposta

Questo potrebbe essere fatto semplicemente in questo modo poiché $? ti fornisce lo stato dellultimo comando eseguito.

Quindi potrebbe essere

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

Commenti

  • Voto negativo: parafrasa semplicemente una risposta precedente che ha giustamente ricevuto critiche per essere unidiomatico.
  • In realtà questo era esattamente quello che stavo cercando perché ‘ ci sto provando per fare in modo che il ” comando ” fallisca lo script come parte di ” set -e ” che non ‘ se ‘ fa parte di if.Questo non dovrebbe ‘ essere sottovalutato.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *