Stratégies de bouclage puissantes : Itérer sur les fichiers et les listes dans les scripts Bash

Maîtrisez les techniques de bouclage Bash essentielles en utilisant `for` et `while` pour automatiser efficacement les tâches système répétitives. Ce guide complet couvre l'itération sur les listes, le traitement des séquences numériques et la gestion robuste des fichiers ligne par ligne en utilisant les meilleures pratiques telles que `while IFS= read -r`. Apprenez la syntaxe fondamentale, le contrôle de boucle avancé (`break`, `continue`) et les techniques essentielles pour un script shell et une automatisation puissants et fiables, accompagnés d'exemples de code pratiques.

35 vues

Stratégies de boucles puissantes : Itération sur les fichiers et les listes dans les scripts Bash

Les boucles Bash sont le moteur de l'automatisation dans le scripting shell. Que vous ayez besoin de traiter chaque fichier d'un répertoire, d'effectuer une tâche un nombre défini de fois, ou de lire des données de configuration ligne par ligne, les boucles fournissent la structure nécessaire pour gérer efficacement les opérations répétitives.

Maîtriser les deux constructions de boucles Bash principales – for et while – est essentiel pour écrire des scripts robustes, évolutifs et intelligents. Ce guide explore la syntaxe fondamentale, les cas d'utilisation pratiques et les meilleures pratiques pour itérer sur des listes, des fichiers, des répertoires et générer des séquences afin de suralimenter vos flux de travail d'automatisation.


La boucle for : Itération sur des ensembles fixes

La boucle for est idéale lorsque vous connaissez à l'avance la collection d'éléments que vous devez traiter. Cette collection peut être une liste explicite de valeurs, les résultats d'une commande ou un ensemble de fichiers trouvés via le globbing.

1. Itération sur des listes standard

Le cas d'utilisation le plus courant implique l'itération sur une liste d'éléments séparés par des espaces.

Syntaxe

for VARIABLE in LISTE_ELEMENTS; do
    # Commandes utilisant $VARIABLE
done

Exemple : Traitement d'une liste d'utilisateurs

# Liste des utilisateurs à traiter
UTILISATEURS="alice bob charlie"

for user in $UTILISATEURS; do
  echo "Vérification du répertoire personnel de $user..."
  if [ -d "/home/$user" ]; then
    echo "$user est actif."
  else
    echo "Avertissement : répertoire personnel de $user manquant."
  fi
done

2. Itération numérique de style C

Pour les tâches qui nécessitent de compter ou des séquences numériques spécifiques, Bash prend en charge une boucle for de style C, souvent combinée à l'expansion d'accolades ou à la commande seq.

Syntaxe (Style C)

for (( INITIALISATION; CONDITION; INCREMENTATION )); do
    # Commandes
done

Exemple : Script de compte à rebours

# Boucle 5 fois (i commence à 1, continue tant que i est inférieur ou égal à 5)
for (( i=1; i<=5; i++ )); do
  echo "Numéro d'itération : $i"
  sleep 1
done
echo "Terminé !"

Alternative : Utilisation de l'expansion d'accolades pour des séquences simples

L'expansion d'accolades est plus simple et plus rapide que l'utilisation de seq pour générer des entiers contigus ou des séquences.

# Génère les nombres de 10 à 1
for num in {10..1}; do
  echo "Compte à rebours : $num"
done

3. Itération sur des fichiers et répertoires (Globbing)

L'utilisation de caractères génériques (*) dans la boucle for vous permet de traiter les fichiers qui correspondent à un modèle spécifique, tels que tous les fichiers journaux ou tous les scripts d'un répertoire.

Exemple : Archivage de fichiers journaux

Il est crucial de mettre les guillemets autour de la variable ("$file") lors de la manipulation de noms de fichiers, en particulier ceux contenant des espaces ou des caractères spéciaux.

REPERTOIRE_CIBLE="/var/log/application"

# Boucle sur tous les fichiers se terminant par .log dans le répertoire cible
for logfile in "$REPERTOIRE_CIBLE"/*.log; do

  # Vérifie si un fichier existe réellement (évite d'exécuter sur le littéral "*.log" si aucun fichier ne correspond)
  if [ -f "$logfile" ]; then
    echo "Compression de $logfile..."
    gzip "$logfile"
  fi
done

La boucle while : Exécution basée sur une condition

La boucle while continue d'exécuter un bloc de commandes tant qu'une condition spécifiée reste vraie. Elle est couramment utilisée pour lire des flux d'entrée, surveiller des conditions ou gérer des tâches dont le nombre d'itérations est inconnu.

1. Boucle while de base

Syntaxe

while CONDITION; do
    # Commandes
done

Exemple : Attente d'une ressource

Cette boucle utilise la commande test ([ ]) pour vérifier si un répertoire existe avant de continuer.

CHEMIN_RESSOURCE="/mnt/data/share"

while [ ! -d "$CHEMIN_RESSOURCE" ]; do
  echo "Attente du montage de la ressource $CHEMIN_RESSOURCE..."
  sleep 5
done

echo "La ressource est disponible. Démarrage de la sauvegarde."

2. Le modèle robuste while read

L'application la plus puissante de la boucle while consiste à lire le contenu d'un fichier ou d'un flux de sortie ligne par ligne. Ce modèle est bien supérieur à l'utilisation d'une boucle for sur la sortie de cat, car il gère de manière fiable les espaces et les caractères spéciaux.

Meilleure pratique : Lecture ligne par ligne

Pour garantir une robustesse maximale, nous utilisons trois composants clés :
1. IFS=: Efface le séparateur de champs interne, garantissant que toute la ligne, y compris les espaces de début/fin, est lue dans la variable.
2. read -r: L'option -r empêche l'interprétation des barres obliques inverses (lecture brute), ce qui est essentiel pour les chemins et les chaînes complexes.
3. Redirection d'entrée (<): Redirige le contenu du fichier dans la boucle, garantissant que la boucle s'exécute dans le contexte shell actuel (évitant les problèmes de sous-shell).

# Fichier contenant des données, un élément par ligne
FICHIER_CONFIG="/etc/app/servers.txt"

while IFS= read -r nom_serveur; do

  # Ignore les lignes vides ou commentées
  if [[ -z "$nom_serveur" || "$nom_serveur" =~ ^# ]]; then
    continue
  fi

  echo "Pinging du serveur : $nom_serveur"
  ping -c 1 "$nom_serveur"

done < "$FICHIER_CONFIG"

Astuce : Éviter cat dans les boucles

N'utilisez jamais cat fichier | while read ligne; do... lors de la lecture de fichiers. Le piping crée un sous-shell, ce qui signifie que les variables définies dans la boucle sont perdues lorsque la boucle se termine. Utilisez plutôt le modèle de redirection d'entrée (while ... done < fichier).

Contrôle avancé des boucles et techniques

Des scripts efficaces nécessitent la capacité de contrôler l'exécution des boucles en fonction des conditions d'exécution.

1. Contrôle du flux : break et continue

  • break: Quitte immédiatement la boucle entière, quelles que soient les itérations ou conditions restantes.
  • continue: Ignore l'itération actuelle et passe immédiatement à l'itération suivante (ou réévalue la condition while).

Exemple : Recherche et arrêt

CIBLE_RECHERCHE="target.conf"

for file in /etc/*; do
  if [ -f "$file" ] && [[ "$file" == *"$CIBLE_RECHERCHE"* ]]; then
    echo "Configuration cible trouvée à : $file"
    break  # Arrêter le traitement une fois trouvée
  elif [ -d "$file" ]; then
    continue # Ignorer les répertoires, vérifier uniquement les fichiers
  fi
  echo "Vérification du fichier : $file"
done

2. Gestion des délimiteurs complexes à l'aide de IFS

Bien que la lecture de fichiers ligne par ligne nécessite d'effacer IFS, l'itération sur une liste séparée par un caractère différent (comme une virgule) nécessite de définir temporairement IFS.

DONNEES_CSV="data1,data2,data3,data4"
ANCIEN_IFS=$IFS # Sauvegarde de l'IFS d'origine
IFS=','       # Définit IFS sur le caractère virgule

for item in $DONNEES_CSV; do
  echo "Élément trouvé : $item"
done

IFS=$ANCIEN_IFS # Restaure l'IFS d'origine immédiatement après la boucle

Avertissement : Modifications globales de IFS

Sauvegardez toujours l' $IFS d'origine avant de le modifier dans un script (par exemple, ANCIEN_IFS=$IFS). Omettre de restaurer la valeur d'origine peut entraîner un comportement imprévisible dans les commandes ultérieures.

Meilleures pratiques pour des boucles Bash robustes

Pratique Justification
Toujours mettre les variables entre guillemets Utilisez "$variable" pour empêcher la division de mots et l'expansion de glob, en particulier lors de l'itération sur des fichiers.
Utiliser while IFS= read -r La méthode la plus fiable pour traiter les fichiers ligne par ligne, gérant correctement les espaces et les caractères spéciaux.
Vérifier l'existence Lors de l'utilisation du globbing (*.txt), incluez toujours une vérification (if [ -f "$file" ];) pour vous assurer que la boucle ne traite pas le nom littéral du modèle si aucun fichier ne correspond.
Localiser les variables Utilisez le mot-clé local dans les fonctions pour empêcher les variables de boucle d'écraser accidentellement des variables globales.
Utiliser les commandes intégrées plutôt que les commandes externes Utilisez l'expansion d'accolades ({1..10}) ou les boucles de style C plutôt que de lancer des commandes externes comme seq pour améliorer les performances.

Conclusion

Les boucles for et while sont fondamentales pour le scripting Bash, permettant des tâches d'automatisation complexes avec une répétition de code minimale. En appliquant systématiquement des modèles robustes – tels que l'approche while IFS= read -r pour le traitement des fichiers et la mise entre guillemets diligente dans les boucles for – vous pouvez créer des scripts fiables, performants et résistants aux formats de données inattendus, apportant une véritable puissance à vos efforts d'automatisation shell.