Comment faire quelque chose de manière conditionnelle si une commande réussit ou échoue

Comment puis-je faire quelque chose comme ça dans bash?

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

Réponse

Comment faire quelque chose de manière conditionnelle si une commande réussit ou échoue

Cest exactement ce que bash Linstruction « s if fait:

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

Ajout dinformations à partir des commentaires: vous ne » t doit utiliser la syntaxe [] dans ce cas. [ est elle-même une commande, presque équivalente à test. Cest probablement la commande la plus courante à utiliser dans un if, qui peut conduire à lhypothèse que cela fait partie de la syntaxe du shell. Mais si vous voulez tester si une commande a réussi ou non, utilisez la commande elle-même directement avec if, comme indiqué ci-dessus.

Commentaires

  • Notez que le point-virgule est important.
  • Ou vous pouvez simplement mettre then sur une ligne distincte.
  • @Joe: Je pense que vous voulez dire if ! command ; then ... ; fi. [ est en soi une commande, et ‘ nest pas nécessaire dans ce cas.
  • @Joe: My way a aussi le mérite dêtre correct. if [ ! command ] nexécute ‘ command; il traite command comme une chaîne et le traite comme vrai car il a une longueur non nulle. [ est un synonyme de la commande test
  • Oups. Vous ‘ avez raison.

Réponse

Pour de petites choses que vous souhaitez exécuter si une commande shell fonctionne, vous pouvez utiliser la construction &&:

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

De même pour les petites choses que vous voulez se produire lorsquune commande shell échoue, vous pouvez utiliser ||:

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

Ou les deux

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

Il est probablement imprudent de faire beaucoup avec ces constructions, mais elles peuvent parfois rendre le flux de contrôle beaucoup plus clair.

Commentaires

  • Ils sont plus courts et (au moins dans certains shells) plus rapides. Je frémis en me souvenant dun script dinstallation Monster Ultrix écrit avec juste ces constructions conditionnelles que jai essayé une fois de déchiffrer …

Réponse

Vérifiez la valeur de $?, qui contient le résultat de lexécution de la commande / fonction la plus récente:

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

Commentaires

  • Bien que techniquement correct (et ne justifiant donc pas un vote défavorable), il ‘ nutilise pas lidiome Bash ‘ s if. Je préfère la réponse de Keith Thompson ‘.
  • Il y a des avantages à cet idiome – il préserve la valeur de retour. Dans lensemble, je trouve celui-ci plus puissant, bien que plus verbeux. il ‘ est également plus facile à lire.
  • Quest-ce que  » Bash ‘ s if idiom « ?
  • @Nowaker Le fait que le seul but de if est de faire ce. Les conditions de contrôle de flux dans Bash examinent toutes $? dans les coulisses; que ‘ est ce quils font. Lexamen explicite de sa valeur ne devrait pas être nécessaire dans la grande majorité des cas, et est généralement un anti-modèle pour débutant.
  • Je préfère cela pour la lisibilité. La commande principale est généralement très longue. Le placer dans une instruction  » si  » entraîne une mauvaise lisibilité.

Réponse

Cela a fonctionné pour moi:

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

if command réussit, puis echo "OK" est exécuté, et comme il est réussi, lexécution sarrête là. Sinon, && est ignoré, et echo "NOK" est exécuté.

Commentaires

  • Si vous voulez faire quelque chose en cas déchec, et conserver le code de sortie (à afficher dans linvite de commande ou à tester dans un script), vous pouvez le faire: command && echo "OK" || c=$?; echo "NOK"; $(exit $c)
  • @ Sam-Hasler: shouldn ‘ t qui soit command && echo "OK" || (c=$?; echo "NOK"; (exit $c))?
  • Aussi, si la partie echo "OK" pouvait elle-même échouer, alors cest mieux: command && (echo "OK"; exit 0) || (c=$?; echo "NOK"; (exit $c))
  • @ jrw32982, Nice, jai ‘ jai utilisé lancienne construction, mais pas ce dernier.
  • La vraie réponse est dans les commentaires, merci à tous!

Réponse

Il convient de noter que if...then...fi et && / || type dapproche traite de létat de sortie renvoyé par la commande que nous voulons tester (0 en cas de succès); cependant, certaines commandes ne renvoient pas un état de sortie différent de zéro si la commande a échoué ou na pas pu traiter lentrée. Cela signifie que les approches habituelles if et && / || ne fonctionneront pas pour ces commandes particulières.

Par exemple, sous Linux, GNU file sort toujours avec 0 sil a reçu un fichier inexistant comme argument et find na pas pu localiser le fichier spécifié par lutilisateur.

$ 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 

Dans de tels cas, une façon potentielle de gérer la situation est de lire stderr / stdin messages, par exemple ceux qui sont retournés par la commande file, ou analysent la sortie de la commande comme dans find. À cette fin, une instruction case pourrait être utilisée.

$ 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éponse

Le plus sujet aux erreurs que jai pu trouver était:

  • Dabord, obtenez la valeur. Supposons que vous fassiez quelque chose comme:

RR=$?

Maintenant, non seulement pour cette situation, mais pour dautres auxquelles vous pourriez être confronté, considérez:

variable définie:

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

Réponse: oui

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

Réponse: non

Variable non définie:

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

Réponse: non

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

Réponse: oui

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

Réponse: oui

Cela évite toutes sortes derreurs.

Vous connaissez probablement toute la syntaxe, mais en voici quelques-unes conseils:

  • Utilisez des guillemets. Évitez quun "blank" soit nothing.
  • La nouvelle notation moderne des variables est ${variable}.
  • Lajout dun zéro concaténé avant votre numéro évite également « pas de nombre du tout ».
  • Mais attendez, lajout dun zéro fait que le nombre devient base-8. Vous obtiendrez une erreur du type:
    • value too great for base (error token is "08") pour les nombres au-dessus de 7. Cest là que 10# entre en jeu:
    • 10# force le nombre à être base-10.

Réponse

Vous pouvez faire ceci:

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

Commentaires

  • Cela fonctionne mais est compliqué. Si vous ‘ exécutez ping dans un sous-shell dun sous-shell, la sortie de ping est capturée en vue de son exécution en tant que commande. Mais comme la sortie est redirigée vers / dev / null, ce sera toujours la chaîne vide. Ainsi, vous ‘ nexécutez rien dans un sous-shell, ce qui signifie que létat de sortie précédent (du sous-shell de substitution de commande, cest-à-dire ping) sera conservé. De toute évidence, la méthode correcte est if ping ...; then ici.

Réponse

Comme indiqué ailleurs dans ce fil de discussion, la question originale répond essentiellement delle-même. Voici une illustration montrant que les conditions if peuvent également être imbriquées.

Cet exemple utilise if pour vérifier si un fichier existe et sil sagit dun fichier normal. Si ces conditions sont vraies, vérifiez sil a une taille supérieure à 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 

Commentaires

  • Cest ce que fait votre réponse, mais votre réponse ne répond pas à la question.
  • @JeffSchaller, merci pour votre note. Jai modifié mon message pour inclure une référence à la question.

Réponse

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

Commentaires

Réponse

Cela pourrait être fait simplement de cette manière comme $? vous donne le statut de la dernière commande exécutée.

Cela pourrait donc être

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

Commentaires

  • Downvote: Ceci paraphrase simplement une réponse précédente qui a été à juste titre critiquée pour son caractère unidiomatique.
  • En fait, cétait exactement ce que je cherchais parce que ‘ jessaye pour que la commande  »  » fasse échouer le script dans le cadre de  » set -e  » ce quil ne fait ‘ t if il ‘ fait partie du if.Cela ne doit pas ‘ être voté contre.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *