web-dev-qa-db-fra.com

Comment faire conditionnellement quelque chose si une commande a réussi ou échoué

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

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

Comment faire conditionnellement quelque chose si une commande a réussi ou échoué

C'est exactement ce que fait l'instruction if de bash:

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

Ajout d'informations à partir des commentaires: vous n'avez pas besoin d'utiliser le [ ... ] syntaxe dans ce cas. [ est lui-même une commande, presque équivalente à test. C'est probablement la commande la plus courante à utiliser dans un if, ce qui peut faire supposer qu'elle 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.

413
Keith Thompson

Pour les petites choses que vous voulez voir se produire si une commande Shell fonctionne, vous pouvez utiliser le && construction:

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

De même pour les petites choses que vous souhaitez voir se produire lorsqu'une 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 peu judicieux de faire grand-chose avec ces constructions, mais elles peuvent parfois rendre le flux de contrôle beaucoup plus clair.

152
Bruce Ediger

Vérifiez la valeur de $?, qui contient le résultat de l'exé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
118
Ryan Stewart

Cela a fonctionné pour moi:

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

si command réussit, alors echo "OK" est exécuté, et comme il réussit, l'exécution s'arrête là. Autrement, && est ignoré et echo "NOK" est exécuté.

52
German Rumm

Il convient de noter que if...then...fi et &&/|| le type d'approche traite du statut de sortie retourné 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 n'a pas pu traiter l'entrée. Cela signifie que les habituels if et &&/|| les approches ne fonctionneront pas pour ces commandes particulières.

Par exemple, sous Linux GNU file se ferme toujours avec 0 s'il a reçu un fichier inexistant en argument et find n'a pas pu localiser le fichier spécifié par l'utilisateur .

$ 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 les messages stderr/stdin, par exemple ceux qui sont retournés par la commande file, ou analysent la sortie de la commande comme dans find. À cette fin, l'instruction case peut ê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
6

La plus sujette aux erreurs que j'ai pu trouver était:

  • Tout d'abord, obtenez la valeur. Supposons que vous fassiez quelque chose comme:

RR=$?

Maintenant, non seulement pour cette situation, mais pour d'autres que vous pourriez rencontrer, pensez à:

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 indé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 d'erreurs.

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

  • Utilisez des guillemets. Évitez qu'un "blank" Soit nothing.
  • La nouvelle notation moderne pour les variables est ${variable}.
  • L'ajout d'un zéro concaténé avant votre numéro évite également "pas de numéro du tout".
  • Mais attendez, l'ajout d'un zéro fait que le nombre devient base-8. Vous obtiendrez une erreur comme:
    • value too great for base (error token is "08") pour les nombres supérieurs à 7. C'est alors que 10# Entre en jeu:
    • 10# Force le nombre à base-10.
4
Dr Beco

Tu peux le faire:

if ($( ping 4.4.4.4 -c1 > /dev/null )) ; then
  echo "ping response succsess!!!"
fi
1
Daniel
#!/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
1
Nick Vladiceanu

Comme indiqué ailleurs dans ce fil, la question d'origine se répond essentiellement. 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 s'il s'agit d'un fichier normal. Si ces conditions sont remplies, vérifiez s'il a ou non 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
1
quartzinquartz