Les structures conditionnelles représentent le cœur logique de tout script Bash efficace. Comprendre comment exploiter les instructions if, else et elif transforme radicalement la capacité à contrôler le flux d’exécution d’un programme, permettant aux scripts de prendre des décisions autonomes en fonction de conditions variables. C’est la différence entre un simple enchaînement de commandes et une véritable automation intelligente, capable d’adapter son comportement à chaque situation rencontrée.

📋 Fondamentaux des structures conditionnelles en Bash : syntaxe et logique
La structure conditionnelle constitue l’élément fondamental sur lequel repose la programmation décisionnelle. En Bash, cette logique s’articule autour de trois mots-clés essentiels : if, then et fi (terminator de la condition). Cette syntaxe épurée reflète la philosophie Unix : faire plus avec moins, tout en restant explicite.
La forme la plus basique démarre avec le mot-clé if, suivi d’une condition enfermée entre crochets. Cette condition peut être une commande système, une comparaison numérique, une vérification de fichier ou même une évaluation de variable. Une fois la condition énoncée, le mot-clé then annonce le bloc de code à exécuter si cette condition s’avère vraie. Le bloc s’achève par fi, qui inverse simplement le mot « if » pour marquer explicitement la fin de la structure.
Voici la syntaxe élémentaire d’une instruction if en Bash :
if [ condition ] then # Bloc de code exécuté si la condition est vraie fiCe modèle, bien que simple, s’étend facilement pour gérer plusieurs scénarios. Lorsqu’une condition s’avère fausse et qu’aucune action alternative n’est définie, le script poursuit son exécution sans intervenir. Cependant, la plupart des situations exigent une réaction spécifique même en cas d’échec, d’où l’introduction de l’instruction else.
🔄 Extension avec else : gérer deux scénarios distincts
L’instruction else permet de définir un bloc alternatif, exécuté uniquement si la condition initiale du if s’avère fausse. Cette bifurcation binaire suffit à de nombreux cas d’usage : vérifier l’existence d’un fichier et réagir différemment selon qu’il existe ou non, valider qu’une variable respecte un seuil numérique, confirmer qu’un service est actif, etc.
Voici la structure avec else :
if [ condition ] then # Bloc exécuté si la condition est vraie else # Bloc exécuté si la condition est fausse fiL’important à retenir : une seule branche s’exécutera. Si la condition est vraie, le bloc then s’exécute et else est entièrement ignoré. Inversement, si la condition est fausse, c’est le bloc else qui s’active tandis que then est contourné.
🎯 Elif : tester plusieurs conditions en cascade
Lorsque plusieurs scénarios doivent être évalués dans une logique séquentielle, elif (contraction de « else if ») intervient. Cette instruction permet de chaîner plusieurs conditions sans recourir à des structures imbriquées complexes, rendant le code plus lisible et plus maintenable.
Voici la syntaxe complète avec elif :
if [ condition1 ] then # Bloc si condition1 est vraie elif [ condition2 ] then # Bloc si condition2 est vraie elif [ condition3 ] then # Bloc si condition3 est vraie else # Bloc si aucune condition n'est vraie fiLa chaîne s’évalue de haut en bas : dès qu’une condition devient vraie, son bloc associé s’exécute et le reste de la structure est ignoré. Cette évaluation court-circuit améliore les performances et prévient les exécutions redondantes. L’instruction else, bien qu’optionnelle, offre une sécurité en gérant le cas où aucune condition précédente n’est satisfaite.
🔢 Opérateurs de comparaison : tester numériquement et textuellement
Bash propose un ensemble d’opérateurs de comparaison spécifiquement conçus pour évaluer des valeurs. Contrairement à certains langages, la syntaxe Bash distingue clairement les comparaisons numériques des comparaisons textuelles, chacune reposant sur des opérateurs différents. Cette distinction prévient les erreurs logiques courantes où une chaîne serait malencontreusement comparée comme nombre.
Pour les comparaisons numériques, Bash emploie des opérateurs abrégés :
- 🔹 -eq : égal (equal)
- 🔹 -ne : non égal (not equal)
- 🔹 -lt : inférieur (less than)
- 🔹 -le : inférieur ou égal (less than or equal)
- 🔹 -gt : supérieur (greater than)
- 🔹 -ge : supérieur ou égal (greater than or equal)
Pour les comparaisons textuelles, d’autres opérateurs interviennent :
- 🔹 = : chaînes identiques
- 🔹 != : chaînes différentes
- 🔹 -z : chaîne vide
- 🔹 -n : chaîne non vide
Un exemple concret illustre cette distinction. Supposons une variable contenant la valeur « 5 ». Si l’on écrit [ $variable -gt 3 ], Bash interprète cela comme une comparaison numérique et retourne vrai. En revanche, [ $variable = « 5 » ] constitue une comparaison textuelle, et bien qu’elle retourne également vrai dans ce cas, elle s’interprète différemment en interne.
🗂️ Opérateurs de test de fichiers et répertoires
Au-delà des nombres et textes, Bash offre des opérateurs pour tester l’état des fichiers du système. Cette catégorie s’avère indispensable en scripting système, où l’existence ou la nature d’un fichier détermine souvent le comportement du script.
| Opérateur | Signification | Exemple |
|---|---|---|
| -e | Fichier ou répertoire existe 📁 | [ -e /home/user/file.txt ] |
| -f | Fichier régulier existe 📄 | [ -f /home/user/script.sh ] |
| -d | Répertoire existe 📂 | [ -d /home/user ] |
| -r | Fichier lisible 👁️ | [ -r /etc/passwd ] |
| -w | Fichier modifiable ✏️ | [ -w /home/user/config ] |
| -x | Fichier exécutable ⚙️ | [ -x /usr/bin/bash ] |
Ces opérateurs s’emploient directement sans variable intermédiaire. Par exemple, [ -f « /path/to/file » ] retourne vrai si le chemin spécifié pointe vers un fichier régulier. Cette simplicité syntaxique en fait un outil puissant pour écrire des scripts défensifs, capables de vérifier leurs conditions avant d’agir.

💡 Exemples pratiques : du concept à l’implémentation
La théorie s’assimile mieux à travers des cas concrets. Voici plusieurs exemples illustrant les structures conditionnelles en action, progressant en complexité pour offrir une compréhension graduée.
🎬 Exemple 1 : vérifier une valeur numérique simple
Imaginons un script de surveillance système qui doit vérifier si l’utilisation du processeur dépasse un seuil critique. Le script lit une variable contenant le pourcentage d’utilisation, puis décide d’afficher un avertissement ou un message rassurant.
#!/bin/bash # Utilisation CPU simulée cpu_usage=75 # Évaluer l'utilisation if [ $cpu_usage -gt 80 ] then echo "⚠️ Alerte CPU critique : utilisation à $cpu_usage%" else echo "✅ CPU normal : utilisation à $cpu_usage%" fiDans ce cas, comme l’utilisation est 75%, elle ne dépasse pas 80, donc le script affiche le message de statut normal. Modifiez la valeur de cpu_usage à 85 pour observer l’affichage de l’alerte.
🎬 Exemple 2 : tester l’existence d’un fichier
Un script d’installation souvent doit déterminer si un fichier de configuration existe déjà avant de créer une version par défaut. Cette vérification prévient les écrasements accidentels.
#!/bin/bash config_file="/etc/myapp/config.conf" if [ -f "$config_file" ] then echo "📄 Fichier de configuration trouvé : $config_file" echo "Utilisation de la configuration existante..." else echo "⚠️ Configuration introuvable" echo "Création d'une configuration par défaut..." # mkdir -p /etc/myapp # cp default.conf "$config_file" fiNotez l’utilisation de guillemets autour de la variable $config_file. Cette pratique, considérée comme une bonne habitude en scripting Bash, prévient les erreurs liées aux espaces dans les chemins.
🎬 Exemple 3 : brancher sur plusieurs conditions avec elif
Un script de gestion de services doit afficher différents messages selon l’état du service. Cette situation illustre parfaitement où elif devient utile.
#!/bin/bash # Récupérer l'état du service service_status=$(systemctl is-active apache2) port_response=$(curl -s -o /dev/null -w "%{http_code}" http://localhost) if [ "$service_status" = "active" ] && [ "$port_response" = "200" ] then echo "✅ Service opérationnel et réactif" elif [ "$service_status" = "active" ] then echo "⚠️ Service actif mais pas de réponse HTTP" elif [ "$service_status" = "inactive" ] then echo "🔴 Service arrêté" else echo "❓ État du service indéterminé" fiCe script évalue successivement trois conditions : d’abord, il vérifie que le service est actif ET que le serveur répond avec un code HTTP 200. Si cette combinaison échoue, il teste si le service est simplement arrêté, puis gère les cas résiduels. Cette chaîne d’évaluation séquentielle rend le diagnostic progressif et exhaustif.
🔗 Combiner des conditions avec les opérateurs logiques
Les scripts réels exigent rarement de vérifier une seule condition. Le plus souvent, plusieurs critères doivent être évalués ensemble ou alternativement. Bash fournit deux opérateurs logiques essentiels : && (ET logique) et || (OU logique).
L’opérateur && (AND) exige que toutes les conditions enchaînées soient vraies. Si l’une d’elles échoue, l’ensemble retourne faux et les conditions suivantes ne sont pas évaluées. À l’inverse, l’opérateur || (OR) retourne vrai dès que l’une des conditions est vraie, sans évaluer les suivantes.
Voici un script de vérification de prérequis systèmes, illustrant l’opérateur && :
#!/bin/bash # Vérifier que l'utilisateur est root ET que Docker est installé if [ $(id -u) -eq 0 ] && command -v docker &> /dev/null then echo "✅ Prérequis satisfaits : administrateur + Docker présent" docker --version else echo "❌ Prérequis manquants" [ $(id -u) -ne 0 ] && echo " - Pas d'accès root" ! command -v docker &> /dev/null && echo " - Docker non installé" fiCe script s’exécute différemment selon que les deux conditions sont satisfaites. Un administrateur sans Docker verra le bloc else s’exécuter. Un utilisateur standard avec Docker installé également. Seul le cas où les deux conditions sont vraies affiche le message de succès.
⚡ Combiner ET et OU dans une même expression
Les scénarios complexes exigent souvent de combiner && et ||. L’ordre d’évaluation suit une logique de priorité : les expressions entre parenthèses s’évaluent d’abord, puis la logique s’applique de gauche à droite.
#!/bin/bash # Vérifier si le système est prêt pour une mise à jour disk_free=50 # GB libres mem_available=4 # GB disponibles is_root=true if ([ $disk_free -gt 30 ] && [ $mem_available -gt 2 ]) || [ $is_root = true ] then echo "✅ Mise à jour possible" else echo "❌ Ressources insuffisantes pour mettre à jour" fiDans ce script, l’expression vérifie soit que l’espace disque ET la mémoire sont suffisants, soit que l’utilisateur a les droits root. Les parenthèses délimitent clairement le premier groupe logique, rendant l’intention explicite et lisible.
🛡️ Bonnes pratiques et pièges courants à éviter
L’écriture de structures conditionnelles robustes exige de connaître les pièges qui attendent les développeurs inexpérimentés. Ces erreurs, souvent subtiles, produisent des comportements imprévisibles ou des faux silencieux.
🔍 L’oubli des guillemets autour des variables
Un classique en scripting Bash : omettre les guillemets autour des variables, particulièrement dans les conditions. Si une variable contient un espace ou reste vide, le script peut se comporter de façon inattendue.
#!/bin/bash # ❌ Dangereux : pas de guillemets username=$1 # Passé en argument, peut contenir des espaces if [ $username = "admin" ] then echo "Accès administrateur" fi # ✅ Correct : avec guillemets if [ "$username" = "admin" ] then echo "Accès administrateur" fiSi l’utilisateur passe « super user » comme argument, la première version échouerait avec une erreur de syntaxe. La deuxième gère correctement les espaces grâce aux guillemets.
⚙️ Confusion entre = et ==
En Bash, l’opérateur de comparaison textuelle est = (unique égal). L’opérateur == fonctionne aussi, mais c’est une extension non-POSIX. Pour la portabilité, préférez toujours l’égal unique.
De plus, l’opérateur == supporte les jokers globaux (*, ?) en Bash moderne, tandis que = les traite littéralement. Cette différence subtile cause des bugs difficiles à diagnoster.
📊 Oublier l’absence de retour logique pour les comparaisons numériques
En Bash, les opérateurs de comparaison numériques (-gt, -lt, -eq, etc.) retournent un code de sortie (0 pour vrai, 1 pour faux), contrairement à d’autres langages qui retournent un booléen. Cela signifie qu’on ne peut pas utiliser directement ces opérateurs en dehors d’un contexte conditionnel sans traiter le code de sortie.
#!/bin/bash # ❌ Dangereux : utiliser directement sans [ ] result=$(-gt 5 3) # Syntaxe invalide # ✅ Correct : les opérateurs -gt, -lt, -eq dans des conditions if [ 5 -gt 3 ] then echo "5 est supérieur à 3" fiCette distinction explique pourquoi Bash exige systématiquement les crochets autour des conditions : ils invoquent le test builtin interne qui traite les opérateurs comparatifs.
⏱️ Évaluation court-circuit et ordre des conditions
Lorsqu’on utilise && et ||, Bash évalue les conditions de gauche à droite et s’arrête dès que le résultat est déterminé. Cela signifie qu’une condition à droite peut ne jamais s’exécuter.
#!/bin/bash # Ordre important pour les performances et les effets secondaires if [ -f "$file" ] && grep -q "pattern" "$file" then echo "Pattern trouvé dans le fichier" fi # Inverse l'ordre : plus lent et inefficace if grep -q "pattern" "$file" && [ -f "$file" ] then echo "Pattern trouvé dans le fichier" fiLe premier cas teste d’abord l’existence du fichier (rapide) avant de chercher un motif (lent). Le second ordre inverse serait inefficace, puisque grep chercherait dans un fichier qui pourrait ne pas exister. Organisez vos conditions du test le plus léger au plus coûteux.
🎯 Cas d’usage avancés : scripts réels et contextes professionnels
Au-delà des exemples introductifs, l’application des conditions conditionnelles dans des scénarios professionnels exige une compréhension nuancée de leur interaction avec d’autres outils Bash. Ces cas réels illustrent comment les concepts fondamentaux se composent pour résoudre des problèmes complexes.
📦 Script de gestion de déploiement avec validation progressive
Un script d’administration système doit souvent vérifier une série de conditions avant de procéder à une action critique comme un déploiement. Cette progression de vérifications constitue une garde-fou contre les erreurs.
#!/bin/bash DEPLOY_USER="deploy" REPO_PATH="/var/www/app" BUILD_DIR="./build" SERVICE_NAME="webapp" # Étape 1 : Vérifier les permissions if [ ! -w "$REPO_PATH" ] then echo "❌ Erreur : pas d'accès en écriture à $REPO_PATH" exit 1 fi # Étape 2 : Vérifier les dépendances de build if [ ! -d "$BUILD_DIR" ] then echo "⚠️ Répertoire build absent, création..." mkdir -p "$BUILD_DIR" fi # Étape 3 : Arrêter le service existant if systemctl is-active --quiet $SERVICE_NAME then echo "🛑 Arrêt du service $SERVICE_NAME..." systemctl stop $SERVICE_NAME sleep 2 elif systemctl is-enabled --quiet $SERVICE_NAME then echo "ℹ️ Service $SERVICE_NAME inactif mais activé" else echo "ℹ️ Service $SERVICE_NAME non trouvé" fi # Étape 4 : Déploiement echo "📦 Déploiement en cours..." # rsync -av source/ "$REPO_PATH/" # Étape 5 : Démarrer le service if systemctl start $SERVICE_NAME then echo "✅ Service $SERVICE_NAME démarré avec succès" else echo "❌ Erreur au démarrage de $SERVICE_NAME" exit 1 fiCe script progresse par étapes, chacune vérifiant une condition avant de poursuivre. Si l’une des conditions critiques échoue (comme l’absence de permissions), le script s’arrête immédiatement via exit 1, prévenant des modifications partielles ou corrompues.
🔐 Script de validation de sécurité pour fichiers sensibles
Dans un contexte de sécurité système, les scripts doivent valider les attributs des fichiers avant de les traiter. Les permissions incorrectes ou les propriétaires non attendus peuvent signaler des tentatives de compromission.
#!/bin/bash SECURE_FILE="/etc/shadow" EXPECTED_OWNER="root" EXPECTED_PERMS="640" # Récupérer les métadonnées file_owner=$(stat -c '%U' "$SECURE_FILE" 2>/dev/null) file_perms=$(stat -c '%a' "$SECURE_FILE" 2>/dev/null) # Valider le propriétaire if [ "$file_owner" != "$EXPECTED_OWNER" ] then echo "🚨 Alerte sécurité : propriétaire incorrect de $SECURE_FILE" echo " Attendu : $EXPECTED_OWNER, Trouvé : $file_owner" fi # Valider les permissions if [ "$file_perms" != "$EXPECTED_PERMS" ] then echo "🚨 Alerte sécurité : permissions incorrectes de $SECURE_FILE" echo " Attendu : $EXPECTED_PERMS, Trouvé : $file_perms" fi # Succès global if [ "$file_owner" = "$EXPECTED_OWNER" ] && [ "$file_perms" = "$EXPECTED_PERMS" ] then echo "✅ Fichier sensible $SECURE_FILE conforme aux normes" fiCe script illustre comment les conditions permettent de valider des aspects critiques de la sécurité système. Les administrateurs peuvent l’intégrer dans des processus de contrôle ou des alertes automatisées.
🔄 Pipeline conditionnel avec exit codes
Un enjeu majeur en scripting Bash professionnel concerne le traitement des codes de sortie (exit codes). Chaque commande retourne un code numérique : 0 indique le succès, toute autre valeur signale une erreur. Les structures conditionnelles se fondent sur cette convention.
#!/bin/bash # Pipeline : exécuter plusieurs commandes en cascade echo "🔄 Mise à jour du système..." # Mise à jour des listes de paquets apt-get update if [ $? -ne 0 ] then echo "❌ Erreur lors de la mise à jour des listes" exit 1 fi # Mise à niveau des paquets apt-get upgrade -y if [ $? -ne 0 ] then echo "❌ Erreur lors de la mise à niveau des paquets" exit 1 fi # Nettoyage apt-get autoclean if [ $? -ne 0 ] then echo "⚠️ Avertissement : nettoyage incomplet" # On ne quitte pas ici, car ce n'est pas critique fi echo "✅ Mise à jour du système réussie"La variable spéciale $? contient le code de sortie de la dernière commande exécutée. Cette technique permet d’établir un flux d’exécution conditionnel robuste, où chaque étape dépend du succès de la précédente.
Maîtriser les structures conditionnelles if, else et elif transcende la syntaxe brute ; c’est développer une capacité à articler la logique décisionnelle d’un système. Ces mécanismes, bien qu’apparemment simples, constituent les fondations sur lesquelles reposent les scripts bash robustes et efficaces, capables de naviguer la complexité des environnements informatiques modernes avec fiabilité et prévisibilité.









