apprenez à maîtriser les boucles for en bash : syntaxe, exemples pratiques et astuces pour automatiser efficacement vos scripts linux.

For cycle Bash : maîtriser les boucles for dans vos scripts Linux

Une boucle for transforme une liste de tâches répétitives en un script fiable : vérifier des serveurs, traiter des fichiers ou parcourir un tableau. En Bash, le résultat dépend autant de la syntaxe choisie que des précautions prises face aux espaces, aux motifs sans correspondance et aux variables modifiées dans une boucle.

L’article en bref

La boucle for convient aux listes et aux fichiers, tandis que while et until répondent à d’autres besoins d’automatisation. Quelques réflexes simples rendent vos scripts Linux plus prévisibles, même lorsque les noms de fichiers sortent de l’ordinaire.

  • Choisir la bonne boucle : for parcourt une liste, while lit un flux, until attend une condition.
  • Parcourir sans découper : préférez les tableaux et les globulations aux sorties de ls.
  • Lire chaque ligne correctement : associez IFS= à read -r pour préserver les données.
  • Éviter les pièges courants : gérez les motifs vides et les sous-shells avant la production.

Quelques règles de syntaxe suffisent pour rendre une itération plus robuste et plus facile à maintenir.

Boucle for Bash : parcourir une liste dans un script Linux

Une boucle répète une action sur les éléments d’un ensemble. Avec for, la liste est connue au moment où le script démarre : des hôtes à vérifier, des fichiers à compresser ou les valeurs contenues dans des tableaux Bash.

Imaginons une équipe qui contrôle régulièrement la disponibilité de ses serveurs. Plutôt que de lancer chaque commande à la main, elle peut confier la vérification à une boucle qui traite une adresse après l’autre et affiche un résultat lisible.

Écrire une boucle for sur une liste connue

La syntaxe de base associe un élément courant à une variable, puis exécute les commandes situées entre do et done. Les guillemets autour de la variable évitent qu’une valeur contenant un espace soit interprétée comme plusieurs arguments.

Exemple : for hote in 127.0.0.1 10.255.255.1; do puis if ping -c1 -W1 « $hote » >/dev/null 2>&1; then echo « $hote : joignable »; else echo « $hote : indisponible »; fi, avant de fermer la boucle avec done. L’option -c1 limite le test à un paquet et -W1 fixe une attente courte, selon l’implémentation de ping installée.

Pour quelques valeurs, cette forme reste claire. Dès que la liste s’allonge, un tableau facilite les modifications et réduit le risque d’oublier un élément.

Utiliser un tableau pour organiser plusieurs valeurs

Un tableau conserve chaque valeur séparément, y compris lorsque celle-ci contient des espaces. L’expansion « ${serveurs[@]} » fournit un argument par élément ; ${#serveurs[@]} donne le nombre d’éléments.

Exemple : serveurs=(« web01 » « web02 » « db01 »), puis for hote in « ${serveurs[@]} »; do printf ‘Vérification : %sn’ « $hote »; done. Cette méthode convient aussi à une liste explicite de fichiers ou de chemins que le script doit traiter plusieurs fois.

A lire aussi :  Doming : qu'est-ce que c'est et sur quels objets l'utiliser

Parcourir des fichiers avec un glob Bash sans casser leurs noms

Pour sélectionner des fichiers dans un répertoire, un motif comme *.log est généralement plus sûr que de transformer la sortie d’une commande en liste. Bash développe directement le motif en noms de fichiers et préserve les espaces, à condition de citer la variable au moment de l’utiliser.

Exemple : for fichier in *.log; do gzip — « $fichier »; done. L’option — indique à gzip que les arguments qui suivent sont des noms et non des options. Avant un traitement destructif, affichez d’abord la sélection avec printf : voir la liste obtenue reste un contrôle simple et utile.

Éviter le piège du répertoire sans correspondance

Par défaut, si aucun fichier ne correspond à *.log, Bash transmet le motif tel quel. La boucle s’exécute alors une fois avec la valeur littérale *.log, qui ne désigne pas nécessairement un fichier existant.

Pour obtenir zéro itération dans ce cas, activez shopt -s nullglob avant la boucle. Cette option modifie le comportement du shell courant ; dans un script réutilisable, tenez-en compte si d’autres motifs sont évalués ensuite. Une autre possibilité consiste à vérifier l’existence du chemin dans la boucle avant d’agir.

Pourquoi éviter for fichier in $(ls)

La sortie de ls est du texte, que Bash peut ensuite découper sur les espaces et interpréter comme des motifs. Un fichier nommé « rapport annuel.log » risque donc de devenir deux éléments, tandis qu’un nom comportant un astérisque peut provoquer des correspondances inattendues.

Pour un répertoire, préférez for fichier in * ou un motif plus ciblé. Pour des noms de fichiers contenant potentiellement des retours à la ligne, utilisez plutôt un traitement délimité par l’octet nul, présenté plus loin.

Choisir entre les deux syntaxes de boucle for en Bash

La boucle sur une liste n’est pas la seule forme disponible. La syntaxe arithmétique, inspirée des langages de programmation comme C, est pratique quand vous avez besoin d’un index, d’un compteur ou d’un incrément précis.

Sa structure est for (( initialisation; condition; incrément )); do …; done. Exemple : for (( i=0; i<5; i++ )); do printf ‘Passage %dn’ « $i »; done. Dans les doubles parenthèses, les variables arithmétiques s’écrivent sans signe dollar dans les comparaisons.

Plages numériques et variables

Pour une petite plage fixe, les accolades offrent une écriture compacte : for i in {1..5}; do printf ‘%sn’ « $i »; done. Un pas peut être précisé, par exemple {0..20..5}, pour parcourir les valeurs par incréments de cinq.

Attention : les accolades sont développées avant les variables. Ainsi, {1..$n} ne construit pas une plage dynamique. Si la limite dépend d’une variable, choisissez plutôt for (( i=1; i<=n; i++ )); do …; done.

Parcourir un tableau avec son index

Lorsque le traitement dépend de la position de chaque élément, la boucle arithmétique permet d’utiliser l’index. Pour éviter de supposer que les indices sont toujours continus, Bash propose aussi « ${!fichiers[@]} », qui développe les indices réellement présents dans le tableau.

Avec for i in « ${!fichiers[@]} »; do printf ‘%s : %sn’ « $i » « ${fichiers[i]} »; done, chaque fichier reste associé à son index. C’est utile pour numéroter des résultats ou comparer des valeurs sans perdre la structure du tableau.

A lire aussi :  Métadonnées photo : comment fonctionnent la localisation et les données GPS

Quand préférer while ou until à la boucle for

Le choix dépend surtout de la source des éléments. For convient à une liste déjà disponible ; while est plus adapté à une lecture progressive, par exemple un fichier texte ou un flux dont le nombre de lignes n’est pas connu.

Pour lire un fichier ligne par ligne, retenez la forme while IFS= read -r ligne; do …; done < fichier. IFS= préserve les espaces en début et en fin de ligne, tandis que -r empêche read d’interpréter les antislashs.

Lire un fichier ou la sortie d’une commande

La redirection d’entrée permet à la boucle de lire le fichier sans faire passer l’exécution dans un sous-shell. Pour traiter la sortie d’une commande tout en conservant les variables modifiées, la substitution de processus est une option pratique : while IFS= read -r ligne; do …; done < <(commande).

À l’inverse, avec commande | while read …, la boucle s’exécute généralement dans un sous-shell en Bash. Une variable incrémentée dans la boucle peut alors retrouver sa valeur initiale après le pipe : un compteur affiché à zéro malgré plusieurs passages est un symptôme classique.

Attendre un service avec until

Until répète son bloc tant que la condition reste fausse. Il convient notamment à l’attente d’un port réseau, à condition de fixer une limite pour éviter qu’un déploiement reste bloqué indéfiniment.

Exemple : essais=0; until nc -z 127.0.0.1 5432 2>/dev/null; do essais=$((essais + 1)); if (( essais >= 30 )); then echo « Service indisponible » >&2; exit 1; fi; sleep 2; done. Le test dépend de la présence de nc et de ses options sur le système ciblé.

Contrôler une boucle avec break et continue

Continue abandonne l’itération en cours et passe à la suivante ; c’est utile pour écarter des lignes vides ou des éléments qui ne répondent pas à un critère. Break quitte immédiatement la boucle, par exemple lorsqu’une erreur bloquante apparaît ou que l’élément recherché est trouvé.

Dans des boucles imbriquées, break quitte par défaut le niveau le plus interne. break 2 sort de deux niveaux, tandis que continue 2 passe à l’itération suivante de la boucle extérieure. Utilisez ces variantes avec mesure : une fonction ou un indicateur d’état peut parfois rendre le déroulement plus lisible.

  • Filtrer une liste : utilisez continue lorsqu’un élément ne doit pas être traité.
  • Arrêter à la première erreur : utilisez break si la suite des opérations n’a plus de sens.
  • Quitter plusieurs niveaux : réservez break 2 aux boucles imbriquées dont la logique est claire.
  • Rendre le diagnostic simple : affichez l’élément courant et la raison de l’arrêt.

Les erreurs fréquentes dans les boucles Bash de production

Un script peut sembler correct dans un dossier de test et échouer sur des noms inhabituels ou un répertoire vide. Tester avec des fichiers contenant des espaces, puis vérifier le comportement lorsque la liste est vide, permet de repérer tôt plusieurs défauts courants.

ShellCheck aide à détecter de nombreuses constructions fragiles avant l’exécution. Il ne remplace pas les tests, mais apporte un contrôle utile sur la syntaxe et les habitudes de programmation shell.

Symptôme Cause possible Précaution
Noms découpés ou traitement en double Utilisation de for f in $(ls) Parcourir un glob ou un tableau cité
Une itération avec *.log Aucun fichier ne correspond au motif Activer nullglob ou vérifier l’existence
Compteur perdu après la boucle La boucle while est à droite d’un pipe Utiliser une redirection ou la substitution de processus
Espaces ou antislashs altérés Lecture avec read sans protections Employer while IFS= read -r ligne
Chemin découpé en plusieurs lignes Nom de fichier contenant un retour à la ligne Associer find -print0 à read -d  »
Plage numérique incorrecte Variable placée dans {1..$n} Utiliser la boucle arithmétique

Traiter les noms de fichiers les plus inhabituels

Les espaces ne posent pas de problème à while IFS= read -r si la lecture est correctement écrite. Le retour à la ligne, en revanche, peut faire croire à la boucle qu’un seul nom correspond à plusieurs entrées, car il sert de séparateur dans une lecture ligne par ligne.

A lire aussi :  Les engins de manutention logistique indispensables pour optimiser vos flux

Pour parcourir une arborescence susceptible de contenir de tels noms, combinez find -print0 avec while IFS= read -r -d  » fichier. L’octet nul ne pouvant pas apparaître dans un nom de fichier Linux, il délimite chaque chemin sans ambiguïté.

Quand éviter une boucle for dans un script Linux

Une boucle n’est pas toujours la solution la plus simple. Si une commande accepte déjà plusieurs chemins, une seule invocation peut remplacer plusieurs appels successifs : chmod 644 ./*.conf évite, par exemple, de lancer chmod pour chaque fichier séparément.

Pour une sélection vide, veillez toutefois à maîtriser le comportement du glob avant de transmettre ses résultats à une commande. Avec un traitement sensible, affichez la liste et vérifiez les options de l’outil : l’automatisation doit rendre l’action plus prévisible, pas plus difficile à contrôler.

Paralléliser les tâches indépendantes

Une boucle for exécute ses itérations l’une après l’autre. Pour des traitements indépendants et longs, xargs avec des options adaptées peut lancer plusieurs tâches en parallèle ; GNU Parallel offre des fonctions supplémentaires lorsque le besoin devient plus avancé.

Le parallélisme demande une vérification supplémentaire : évitez que plusieurs tâches écrivent dans le même fichier ou modifient simultanément une ressource partagée. Choisir entre une boucle, xargs ou un outil dédié dépend donc autant des performances recherchées que des effets de chaque opération.

Choisir la bonne boucle Bash selon la tâche

Avant d’écrire le script, identifiez la forme de vos données : une liste prête, des lignes à lire, un compteur ou un événement à attendre. Cette décision donne une structure claire à la boucle et aide à choisir les protections nécessaires.

Besoin Forme adaptée Point de vigilance
Parcourir une liste ou un tableau for élément in « ${liste[@]} » Citer les expansions
Traiter des fichiers d’un répertoire for fichier in *.log Prévoir le cas sans correspondance
Lire un fichier ligne par ligne while IFS= read -r ligne Rediriger le fichier sur la boucle
Lire la sortie d’une commande while … done < <(commande) Éviter le pipe si des variables doivent survivre
Parcourir une arborescence aux noms atypiques find -print0 avec read -d  » Conserver le délimiteur nul de bout en bout
Attendre qu’une condition devienne vraie until condition Ajouter un délai maximal et une sortie d’erreur
Incrémenter un index ou un compteur for (( i=0; i<n; i++ )) Vérifier les bornes de la condition

Une règle simple guide la plupart des cas : for pour une liste connue, while pour une lecture progressive, until pour attendre un événement. Avant d’ajouter une boucle, vérifiez aussi si la commande ne sait pas déjà traiter plusieurs arguments.

Questions fréquentes sur les boucles for en Bash

Ces réponses résument les choix de syntaxe et les précautions qui rendent les scripts plus faciles à tester et à maintenir.

Quand choisir for plutôt que while en Bash ?

Choisissez for lorsque vous avez une liste, un tableau, un glob ou un nombre d’itérations déterminé. Préférez while pour lire progressivement un fichier ou un flux.

Pourquoi éviter for fichier in $(ls) ?

La sortie de ls peut être découpée sur les espaces puis réinterprétée comme des motifs. Un glob comme *.log ou un tableau cité préserve mieux les noms de fichiers.

À quoi servent IFS= et read -r ?

IFS= préserve les espaces en bordure de ligne et read -r empêche l’interprétation des antislashs. Ensemble, ils forment une base fiable pour lire un fichier ligne par ligne.

Comment parcourir une plage qui dépend d’une variable ?

Utilisez une boucle arithmétique, par exemple for (( i=1; i<=n; i++ )). La forme {1..$n} ne développe pas la variable comme une borne dynamique.

Comment attendre un service sans bloquer indéfiniment ?

Une boucle until peut tester le port ou la condition attendue, mais doit comporter une limite de tentatives, une temporisation et une sortie en erreur.

Retour en haut