Tous les langages de programmation raisonnablement complets sont capables de tester des conditions, puis d'agir en fonction du résultat du test. Bash dispose de la commande test, de différents opérateurs à base de crochets et de parenthèses, ainsi que des contrôles if/then.
Un contrôle if/then teste si l'état de la sortie d'une liste de commandes vaut 0 (car 0 indique le « succès » suivant les conventions UNIX) et, dans ce cas, exécute une ou plusieurs commandes.
Il existe une commande dédiée appelée [ (caractère spécial crochet gauche). C'est un synonyme de test, qui est intégré pour des raisons d'optimisation. Cette commande considère ses arguments comme des expressions de comparaisons ou comme des tests de fichiers et renvoie un état de sortie correspondant au résultat de la comparaison (0 pour vrai et 1 pour faux).
Avec la version 2.02, Bash a introduit la commande de test étendue [[ ... ]], réalisant des comparaisons d'une façon familière aux programmeurs venant d'autres langages. Notez que [[ est un mot clé, pas une commande.
Bash considère l'expression [[ $a -lt $b ]] comme un seul élément, renvoyant un état de sortie.
Les expressions (( ... )) et let ... renvoient un code de sortie qui dépend du fait que les expressions arithmétiques qu'elles évaluent se résolvent en une valeur non nulle. Cette syntaxe avec des expansions arithmétiques peut par conséquent être utilisée pour des comparaisons arithmétiques.
(( 0 && 1 )) # 'ET' logique echo $? # 1 *** # Et donc ... let "num = (( 0 && 1 ))" echo $num # 0 # Mais ... let "num = (( 0 && 1 ))" echo $? # 1 *** (( 200 || 11 )) # 'OU' logique echo $? # 0 *** # ... let "num = (( 200 || 11 ))" echo $num # 1 let "num = (( 200 || 11 ))" echo $? # 0 *** (( 200 | 11 )) # 'OU' bit à bit echo $? # 0 *** # ... let "num = (( 200 | 11 ))" echo $num # 203 let "num = (( 200 | 11 ))" echo $? # 0 *** # L'expression en "let" renvoie le même statut de sortie #+ que l'expression arithmétique avec les doubles-parenthèses.DIFF63
Un if peut tester n'importe quelle commande, pas seulement des conditions entourées par des crochets.
if cmp a b &> /dev/null # Supprime la sortie. then echo "Les fichiers a et b sont identiques." else echo "Les fichiers a et b sont différents." fi # L'expression "if-grep" très utile: # ------------------------------------- if grep -q Bash fichier then echo "fichier contient au moins une occurrence du mot Bash." fi mot=Linux sequence_lettres=inu if echo "$mot" | grep -q "$sequence_lettres" # L'option "-q" de grep supprime l'affichage du résultat. then echo "$sequence_lettres trouvé dans $mot" else echo "$sequence_lettres non trouvé dans $mot" fi if COMMANDE_DONT_LA_SORTIE_EST_0_EN_CAS_DE_SUCCES then echo "La commande a réussi." else echo "La commande a échoué." fi
Les deux exemples précédents sont de Stéphane Chazelas.
Exercice. Expliquez le comportement de l'Exemple 7.1, « Où est la vérité ? », ci-dessus.
if [ condition-vraie ] then commande 1 commande 2 ... else # Sinon... # Ajoute un code par défaut à exécuter si la première condition se # fausse. commande 3 commande 4 ... fi
Quand if et then sont sur la même ligne lors d'un test, un point-virgule doit finir l'expression if. if et then sont des mots clés. Les mots clés (et les commandes) commençant une expression doivent être terminés avant qu'une nouvelle expression sur la même ligne puisse commencer.
if [ -x "$nom_fichier" ]; then
elif est une contraction pour else if. L'effet produit est l'inclusion d'une boucle en if/then dans une autre boucle déjà commencée.
if [ condition1 ] then commande1 commande2 commande3 elif [ condition2 ] # Idem que else if then commande4 commande5 else commande_par_defaut fi
Le contrôle if test condition-vraie est l'exact équivalent de if [ condition-vraie ]. De cette façon, le crochet gauche, [, est un raccourci DIFF63 [30] appelant la commande test. Le crochet droit fermant, ], ne devrait donc pas être nécessaire dans un test if , néanmoins, les dernières versions de Bash le requièrent.
La commande test est une commande interne de Bash, permettant de tester les types de fichiers et de comparer des chaînes de caractères. Donc, dans un script Bash, test n'appelle pas le binaire externe /usr/bin/test, qui fait partie du paquet sh-utils. De même, [ n'appelle pas /usr/bin/[, qui est un lien vers /usr/bin/test.
bash$ type test test is a shell builtin bash$ type '[' [ is a shell builtin bash$ type '[[' [[ is a shell keyword bash$ type ']]' ]] is a shell keyword bash$ type ']' bash: type: ]: not found
Si pour une raison ou une autre vous souhaitez utiliser /usr/bin/test dans un script Bash, alors indiquez le chemin complet.
Après un if, ni la commande test ni les crochets de test ( [ ] ou [[ ]] ) ne sont nécessaires.
repertoire=/home/bozo if cd "$repertoire" 2>/dev/null; then # "2>/dev/null" cache les messages d'erreur echo "Je suis maintenant dans $repertoire." else echo "Je ne peux pas aller dans $repertoire." fi
L'expression « if COMMANDE » renvoie l'état de sortie de la COMMANDE.
De manière identique, une condition à l'intérieur de crochets de test peut fonctionner sans if si elle est utilisée avec une construction en liste.
var1=20 var2=22 [ "$var1" -ne "$var2" ] && echo "$var1 n'est pas égal à $var2" home=/home/bozo [ -d "$home" ] || echo "Le répertoire $home n'existe pas."
La syntaxe (( )) permet d'évaluer une expression arithmétique. Si l'expression vaut 0, elle renvoie un code de sortie de 1, ou « false ». Une expression différente de 0 renvoie 0 ou « true ». Ceci est en totale contradiction avec l'utilisation des contrôles test et [ ] évoquées précédemment.
Exemple 7.3. Tests arithmétiques en utilisant (( ))
#!/bin/bash # Tests arithmétiques. # La construction (( ... )) évalue et teste les expressions numériques. # Code de sortie opposé à la construction [ ... ] ! (( 0 )) echo "Le code de sortie de \"(( 0 ))\" est $?." # 1 (( 1 )) echo "Le code de sortie de \"(( 1 ))\" est $?." # 0 (( 5 > 4 )) # vrai echo "Le code de sortie de \"(( 5 > 4 ))\" est $?." # 0 (( 5 > 9 )) # faux echo "Le code de sortie de \"(( 5 > 9 ))\" est $?." # 1 (( 5 - 5 )) # 0 echo "Le code de sortie de \"(( 5 - 5 ))\" est $?." # 1 (( 5 / 4 )) # Division OK. echo "Le code de sortie de \"(( 5 / 4 ))\" est $?." # 0 (( 1 / 2 )) # Résultat de la division < 1. echo "Le code de sortie de \"(( 1 / 2 ))\" est $?." # Arrondie à 0. # 1 (( 1 / 0 )) 2>/dev/null # Division par 0... illégale. # ^^^^^^^^^^^ echo "Le code de sortie de \"(( 1 / 0 ))\" est $?." # 1 # Quel effet a "2>/dev/null"? # Qu'arriverait-t'il s'il était supprimé? # Essayez de le supprimer, et ré-exécutez le script. exit 0
[30] A token is a symbol or short string with a special meaning attached to it (a meta-meaning). In Bash, certain tokens, such as [ and . (dot-command), may expand to keywords and commands.