Une construction 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 pour test, qui est intégré pour des raisons d'optimisation. Cette commande prend ses arguments comme des expressions de comparaisons ou comme des tests de fichiers et renvoit 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 [[ $a -lt $b ]] comme un seul élément, renvoyant un état de sortie.
Les constructions (( ... )) et let ... renvoient aussi un état de sortie de 0 si les expressions arithmétiques qu'elles évaluaient se résolvent en une valeur non nulle. Ces constructions d'expansion arithmétique peuvent donc être utilisées pour réaliser des comparaisons arithmétiques.
let "1<2" renvoie 0 (car "1<2" se transforme en "1") (( 0 && 1 )) renvoie 1 (car "0 && 1" donne "0") |
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 if grep -q Bash fichier then echo "fichier contient au moins une occurrence du mot Bash." fi if COMMANDE_DONT_LA_SORTIE_EST_0_EN_CAS_DE_SUCCES then echo "Commande réussie." else echo "Commande echouée." fi |
Une construction if/then peut contenir des comparaisons et des tests imbriqués.
if echo "Le *if* suivant fait partie de la comparaison du premier *if*." if [[ $comparaison = "integer" ]] then (( a < b )) else [[ $a < $b ]] fi then echo '$a est plus petit que $b' fi |
L'explication détaillée du << if-test >> provient de Stephane Chazelas.
Exemple 7-1. Où est le vrai?
#!/bin/bash echo echo "Test de \"0\"" if [ 0 ] # zéro then echo "0 est vrai." else echo "0 est faux." fi # 0 est vrai. echo echo "Test de \"1\"" if [ 1 ] # un then echo "1 est vrai." else echo "1 est faux." fi # 1 est vrai. echo echo "Test de \"-1\"" if [ -1 ] # moins un then echo "-1 est vrai." else echo "-1 est faux." fi # -1 est vrai. echo echo "Test de \"NULL\"" if [ ] # NULL (condition vide) then echo "NULL est vrai." else echo "NULL est faux." fi # NULL est faux. echo echo "Test de \"xyz\"" if [ xyz ] # chaîne de caractères then echo "Chaîne de caractères au hasard est vrai." else echo "Chaîne de caractères au hasard est faux." fi # Chaîne de caractères au hasard est vrai. echo echo "Test de \"\$xyz\"" if [ $xyz ] # Teste si $xyz est nul, mais... # c'ets seulement une variable non initialisée. then echo "Une variable non initialisée est vrai." else echo "Une variable non initialisée est faux." fi # Une variable non initialisée est faux. echo echo "Test de \"-n \$xyz\"" if [ -n "$xyz" ] # Plus correct. then echo "Une variable non initialisée est vrai." else echo "Une variable non initialisée est faux." fi # Une variable non initialisée est faux. echo xyz= # Initialisé, mais à une valeur nulle. echo "Test de \"-n \$xyz\"" if [ -n "$xyz" ] then echo "Une variable nulle est vrai." else echo "Une variable nulle est faux." fi # Une variable nulle est faux. echo # Quand "faux" est-il vrai? echo "Test de \"false\"" if [ "false" ] # Il semble que "false" ne soit qu'une chaîne de #+ caractères. then echo "\"false\" est vrai." #+ et il est testé vrai. else echo "\"false\" est faux." fi # "false" est vrai. echo echo "Test de \"\$false\"" # De nouveau, une chaîne non initialisée. if [ "$false" ] then echo "\"\$false\" est vrai." else echo "\"\$false\" est faux." fi # "$false" est faux. # Maintenant, nous obtenons le résultat attendu. echo exit 0 |
Exercice. Expliquez le comportement de Exemple 7-1, ci-dessus.
if [ condition-vraie ] then commande 1 commande 2 ... else # Optionnel (peut être oublié si inutile). # Ajoute un code par défaut à exécuter si la condition originale se révèle # 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.
|
elif est une contraction pour else if. Le but est de faire tenir une construction if/then dans une autre construction déjà commencée.
if [ condition1 ] then commande1 commande2 commande3 elif [ condition2 ] # Idem que else if then commande4 commande5 else commande_par_defaut fi |
La construction if test condition-vraie est l'exact équivalent de if [ condition-true ]. De cette façon, le crochet gauche, [, est un raccourci 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.
|
Exemple 7-2. Equivalences de test, /usr/bin/test, [ ], et /usr/bin/[
#!/bin/bash echo if test -z "$1" then echo "Pas arguments sur la ligne de commande." else echo "Le premier argument de la ligne de commande est $1." fi echo if /usr/bin/test -z "$1" # Même résultat que la commande intégrée "test". then echo "Pas arguments sur la ligne de commande." else echo "Le premier argument de la ligne de commande est $1." fi echo if [ -z "$1" ] # Identique fonctionnellement au bloc de code. # if [ -z "$1" devrait fonctionner, mais... #+ Bash répond qu'un crochet fermant manque. then echo "Pas arguments sur la ligne de commande." else echo "Le premier argument de la ligne de commande est $1." fi echo if /usr/bin/[ -z "$1" # Encore une fois, fonctionnalité identique à #+ ci-dessus. # if /usr/bin/[ -z "$1" ] # Fonctionne, mais donne un message d'erreur. then echo "Pas arguments sur la ligne de commande." else echo "Le premier argument de la ligne de commande est $1." fi echo exit 0 |
La construction [[ ]] est l'équivalent shell de [ ]. C'est la commande étendue de test, venant de ksh88.
![]() | Il n'est pas possible de faire de la complétion de noms de fichiers ou de la séparation de mots lorsqu'on se trouve entre [[ et ]], mais la complétion de paramètres et la substitution de commandes sont disponibles. |
fichier=/etc/passwd if [[ -e $fichier ]] then echo "Le fichier de mots de passe existe." fi |
![]() | Utiliser la construction [[ ... ]], au lieu de [ ... ] peut vous permettre d'éviter des erreurs de logique dans vos scripts. Par exemple, les opérateurs &&, ||, < et > fonctionnent à l'intérieur d'un test [[ ]] bien qu'ils génèrent une erreur à l'intérieur d'une construction [ ]. |
![]() | Après un if, ni la commande test ni les crochets de test ( [ ] ou [[ ]] ) ne sont nécessaires.
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.
|
La construction (( )) évalue 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 constructions 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 exepressions 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 relancer le script. exit 0 |
Précédent | Sommaire | Suivant |
Tests | Niveau supérieur | Opérateurs de test de fichiers |