Retour au cours

boucles for while

Objectifs

  • Itérer sur une liste d’éléments (fichiers, arguments, chaînes) avec une boucle for.
  • Répéter une action tant qu’une condition est vraie avec une boucle while.
  • Lire un fichier ligne par ligne de manière robuste et sécurisée.
  • Utiliser des compteurs et des boucles de style C.

Explications détaillées

Notions clés

Les boucles sont des structures fondamentales qui permettent de répéter un bloc de code plusieurs fois. Bash en propose principalement deux types : for et while.

La boucle for : Pour chaque élément d’une liste…

La boucle for est idéale pour parcourir une liste prédéfinie d’éléments.

Syntaxe :

for variable in element1 element2 element3; do
  # Commandes à exécuter pour chaque élément
  # La variable contient l'élément courant
done

Les “éléments” peuvent être fournis par une expansion de globbing (*), des arguments de script ($@), la sortie d’une commande ($(...)), ou une séquence générée ({1..5}).

La boucle while : Tant que la condition est vraie…

La boucle while est parfaite lorsque le nombre de répétitions n’est pas connu à l’avance. Elle continue de tourner tant qu’une commande de test renvoie un code de sortie 0 (succès).

Syntaxe :

while [[ condition ]]; do
  # Commandes à exécuter
  # Il est crucial de faire évoluer la condition ici pour éviter une boucle infinie
done

La boucle until

C’est l’inverse de while. La boucle s’exécute tant que la condition est fausse. Elle est moins courante mais peut parfois clarifier l’intention.

until [[ condition ]]; do
  # ...
done

Lire un fichier ligne par ligne

C’est un cas d’usage si fréquent qu’il mérite son propre motif. La méthode la plus sûre, qui préserve les espaces et les caractères spéciaux, est la suivante :

while IFS= read -r line; do
  echo "Ligne lue : ->$line<-"
done < "mon_fichier.txt"
  • read -r : Empêche l’interprétation des backslashs.
  • IFS= : Empêche la suppression des espaces en début et fin de ligne.
  • < "mon_fichier.txt" : Redirige le contenu du fichier vers l’entrée standard de la boucle while.

Syntaxe / Usages

# Itérer sur des fichiers
for f in *.txt; do
  echo "Traitement du fichier $f"
done

# Itérer sur les arguments d'un script
for arg in "$@"; do
  echo "Argument reçu : $arg"
done

# Compteur avec 'while'
i=0
while [[ $i -lt 5 ]]; do
  echo "i = $i"
  ((i++))
done

# Boucle de style C (plus concise pour les compteurs)
for (( c=1; c<=5; c++ )); do
  echo "Compteur C : $c"
done

Exemples

# 1. Renommer des fichiers en masse
# Créez quelques fichiers pour tester : touch image.jpeg photo.JPEG
for f in *.jpeg *.JPEG; do
  # On remplace l'extension par .jpg
  mv -- "$f" "${f%.*}.jpg"
  echo "Renommé '$f' en '${f%.*}.jpg'"
done

# 2. Attendre qu'un service soit prêt
# (Simulation)
# until ping -c 1 mon_serveur &> /dev/null; do
#   echo "Le serveur ne répond pas, on attend 5 secondes..."
#   sleep 5
# done
# echo "Le serveur est en ligne !"

# 3. Traiter un fichier CSV simple
# Fichier "users.csv":
# 1,alice
# 2,bob
# Créez ce fichier avant de lancer le script
while IFS=',' read -r id name; do
  echo "Utilisateur ID $id a pour nom $name"
done < users.csv

Bonnes pratiques

  • Ne JAMAIS faire de boucle sur la sortie de ls (for i in $(ls *.txt)). C’est la pire pratique en scripting shell car elle casse dès qu’un nom de fichier contient des espaces. Utilisez directement le globbing : for i in *.txt.
  • Toujours utiliser le motif while IFS= read -r line pour lire des fichiers. Toute autre méthode est moins robuste.
  • Pour les compteurs, la syntaxe for ((...)) est souvent plus claire et plus performante qu’une boucle while avec incrémentation manuelle.

Pièges courants

  • Boucles infinies : Si la condition d’une boucle while n’est jamais mise à jour pour devenir fausse, le script tournera à l’infini.
  • Problèmes d’espaces : Oublier de citer une variable ("$item") dans une boucle for peut causer des problèmes si les éléments contiennent des espaces.
  • Variables dans un pipe : Une boucle while alimentée par un pipe s’exécute dans un subshell. Toute variable que vous y modifiez sera perdue à la fin de la boucle. cat file | while ... { ma_var=10; } ; echo $ma_var n’affichera rien.

Exercices

  1. Sauvegarde de fichiers de configuration :

    • Écrivez un script qui trouve tous les fichiers se terminant par .conf dans le dossier /etc (sans descendre dans les sous-dossiers).
    • Pour chaque fichier trouvé, il doit le copier dans un dossier ~/backup_conf (que vous créerez au début du script).
  2. Compte à rebours :

    • Écrivez un script qui prend un nombre en argument.
    • Il doit afficher un compte à rebours de ce nombre jusqu’à 1, avec une pause d’une seconde entre chaque nombre, puis afficher “Terminé !”. Utilisez une boucle while.
  3. Lecteur de liste :

    • Créez un fichier taches.txt avec une tâche par ligne.
    • Écrivez un script qui lit ce fichier et affiche chaque tâche précédée de son numéro de ligne (ex: “1. Faire les courses”). Utilisez while read.