Aller au contenu

Bash : conditions et boucles

Les conditions et les boucles contrôlent le déroulement d’un script. Les exemples utilisent des noms génériques.

Fenêtre de terminal
if [[ -f "$fichier" ]]; then
echo "Le fichier existe"
elif [[ -d "$fichier" ]]; then
echo "C'est un dossier"
else
echo "Introuvable"
fi

Les doubles crochets [[ ... ]] sont la forme recommandée dans un script Bash ; les crochets simples [ ... ] fonctionnent aussi dans sh, mais sont plus fragiles (guillemets obligatoires).

if teste le code de sortie d’une commande : toute commande peut servir de condition.

Fenêtre de terminal
if grep -q "erreur" journal.log; then # -q : n'affiche rien, ne sert qu'au code de sortie
echo "Des erreurs ont été trouvées"
fi
if ! systemctl is-active --quiet ssh; then
echo "SSH est arrêté"
fi
Test Vrai si
-e f f existe
-f f f est un fichier ordinaire
-d f f est un dossier
-r f / -w f / -x f f est lisible / modifiable / exécutable
-s f f existe et n’est pas vide
-L f f est un lien symbolique
f1 -nt f2 f1 est plus récent que f2
Test Vrai si
-z "$s" la chaîne est vide
-n "$s" la chaîne n’est pas vide
"$a" == "$b" les chaînes sont égales
"$a" != "$b" les chaînes sont différentes
"$s" == motif* la chaîne correspond au motif (sans guillemets sur le motif)
"$s" =~ ^[0-9]+$ la chaîne correspond à l’expression régulière
Fenêtre de terminal
if [[ "$reponse" == [oO]* ]]; then echo "Oui"; fi
if [[ "$age" =~ ^[0-9]+$ ]]; then echo "Nombre entier"; fi
Test Signification
-eq / -ne égal / différent
-lt / -le inférieur / inférieur ou égal
-gt / -ge supérieur / supérieur ou égal
Fenêtre de terminal
if [[ "$nb" -gt 10 ]]; then echo "Plus de 10"; fi
if (( nb > 10 )); then echo "Plus de 10"; fi # forme arithmétique, plus lisible
Fenêtre de terminal
if [[ -f "$f" && -r "$f" ]]; then echo "Fichier lisible"; fi
if [[ "$a" == "x" || "$b" == "y" ]]; then echo "Au moins une vraie"; fi
[[ -d "$dossier" ]] || mkdir -p "$dossier" # crée le dossier s'il manque
command -v rsync >/dev/null && echo "rsync est installé"

Alternative lisible à plusieurs if successifs :

Fenêtre de terminal
case "$1" in
start)
echo "Démarrage" ;;
stop|arret)
echo "Arrêt" ;;
*.txt)
echo "Fichier texte" ;;
*)
echo "Usage : $0 {start|stop}" >&2
exit 1 ;;
esac
Fenêtre de terminal
for fruit in pomme poire cerise; do
echo "$fruit"
done
for fichier in *.log; do # fichiers du dossier courant
echo "Traitement de $fichier"
done
for i in {1..5}; do echo "$i"; done # de 1 à 5
for ((i = 0; i < 5; i++)); do # boucle « à la C »
echo "$i"
done
Fenêtre de terminal
compteur=1
while (( compteur <= 3 )); do
echo "Tour $compteur"
(( compteur++ ))
done
until ping -c 1 -W 2 exemple.com >/dev/null 2>&1; do # jusqu'à ce que la commande réussisse
echo "En attente du réseau..."
sleep 5
done
Fenêtre de terminal
while IFS= read -r ligne; do
echo "Ligne : $ligne"
done < fichier.txt

IFS= et -r conservent les espaces et les antislashs tels quels. Pour traiter la sortie d’une commande :

Fenêtre de terminal
while IFS= read -r utilisateur; do
echo "Utilisateur : $utilisateur"
done < <(cut -d: -f1 /etc/passwd)
Fenêtre de terminal
for n in {1..10}; do
(( n % 2 == 0 )) && continue # passe au tour suivant
(( n > 7 )) && break # sort de la boucle
echo "$n"
done
Fenêtre de terminal
read -r -p "Continuer ? [o/N] " reponse
if [[ "$reponse" =~ ^[oO]$ ]]; then
echo "On continue"
else
echo "Annulé"
exit 0
fi