Script Bash : comment utiliser les boucles For ?
Sommaire
I. Présentation
Dans ce tutoriel, nous allons apprendre à utiliser les boucles For (ForEach) dans un script Bash. Les boucles For seront utiles lors de la rédaction de scripts Bash pour automatiser des tâches répétitives puisque nous allons effectuer une opération plusieurs fois.
Nous verrons comment utiliser les boucles For en Bash avec plusieurs exemples concrets. Mais, avant cela, nous allons évoquer la structure de base d'une boucle For en Bash.
En complément de cet article, nous vous recommandons la lecture de celui-ci :
II. Syntaxe d'une boucle For en Bash
D'abord, sachez qu'en Bash, c'est l'instruction "For" qui est utilisée pour les boucles For, mais aussi les boucles ForEach, contrairement à d'autres langages où il y a des mots clés distincts. La boucle For en Bash itère sur une liste d'éléments et exécute un bloc de code pour chaque élément, ce qui permet d'effectuer un traitement sur chaque élément.
Il y a deux manières d'écrire une boucle For en Bash, ce qui est aussi une façon de différencier "For" et "ForEach". Avec une boucle "ForEach" nous allons chercher à parcourir l'ensemble des éléments, tandis qu'avec une boucle "For" classique, ceci dépendra de la condition de répétition.
Voici la syntaxe de base (correspondant à un ForEach) :
for <Element> in <Liste des élements>
do
# Commandes à exécuter pour chaque élément
done
Voici une autre façon d'écrire la boucle For (syntaxe à trois expressions) :
for ((<Etat initial> ; <Condition répétition> ; <Incrémenter à chaque itération>))
do
# Commandes à exécuter pour chaque élément
done
Voyons maintenant comment mettre en œuvre les boucles For au sein d'exemples.
III. Prise en main des boucles For
Tout d'abord, avant de passer à des exemples concrets, voici un premier exemple pour mettre en pratique les deux syntaxes évoquées précédemment. Il va simplement permettre de parcourir les nombres de 1 à 5, afin d'afficher un message pour chaque nombre de la liste.
Les deux extraits de code présentés ci-dessous permettent d'obtenir le même résultat, tout en exploitant les deux syntaxes possibles pour une boucle For.
Voici le premier bout de code :
#!/bin/bash
for i in 1 2 3 4 5
do
echo "Etape numéro $i"
done
Remarque : la liste de valeurs "1 2 3 4 5" peut être remplacée par "{1..5}".
Ce premier exemple retourne le résultat suivant :
Voici le second bout de code :
#!/bin/bash
for (( i=1; i<=5; i++ ))
do
echo "Etape numéro $i"
done
Ce second exemple retourne le résultat suivant :
IV. Boucle For sur une liste de fichiers
Nous pouvons utiliser une boucle For en Bash pour effectuer un traitement sur une liste de fichiers. Voici un exemple où la boucle For est utilisée pour itérer sur une liste de fichiers afin d'afficher le nombre de lignes présentes dans chaque fichier. Ici, la liste d'éléments à traiter correspond à l'ensemble des fichiers ".txt" présents dans le répertoire "/home/flo/Documents/".
#!/bin/bash
for fichier in /home/flo/Documents/*.txt
do
echo "$fichier : $(cat $fichier | wc -l) ligne(s)"
done
Voici le résultat retourné par le script sur ma machine de test :
/home/flo/Documents/document1.txt : 1 ligne(s)
/home/flo/Documents/document2.txt : 1 ligne(s)
/home/flo/Documents/document3.txt : 3 ligne(s)
/home/flo/Documents/document4.txt : 10 ligne(s)
/home/flo/Documents/document5.txt : 5 ligne(s)
J'en profite pour attirer votre attention sur l'instruction "$(cat $fichier | wc -l)" intégrée à la ligne présentée ci-dessous. Ceci permet de substituer l'instruction comprise dans le bloc "$()" par le résultat, à savoir ici le nombre de lignes du fichier.
echo "$fichier : $(cat $fichier | wc -l) ligne(s)"
Passons à un autre exemple pratique.
V. Boucle For pour renommer des fichiers
Un script Bash peut être très utile pour renommer en masse des fichiers sur une machine Linux. Dans l'exemple ci-dessous, nous ajoutons le préfixe "itconnect_" à tous les fichiers ".txt" présents dans le répertoire courant (vis-à-vis du prompt). Ces quelques lignes de code peuvent nous faire gagner un temps précieux.
#!/bin/bash
for fichier in *.txt
do
mv "$fichier" "itconnect_$fichier"
done
Voici le résultat obtenu :
Nous pourrions aussi conserver le nom actuel, mais remplacer un caractère par un autre. Ceci peut être utile pour supprimer les espaces dans les noms et indiquer un tiret à la place, par exemple. Dans la continuité de l'exemple précédent, nous allons remplacer le caractère "_" par "-".
La syntaxe à utiliser est la suivante. Nous faisons appel au mécanisme d'expansion de variable ("${}").
#!/bin/bash
for fichier in *.txt
do
mv "$fichier" "${fichier//_/-}"
done
Voici quelques explications :
- "fichier" est la variable contenant la chaîne d'origine, ici le nom du fichier
- "//" indique que toutes les occurrences de la chaîne doivent être remplacées.
- "_" est la chaîne à remplacer.
- "-" est la chaîne de substitution
Nous obtenons bien le résultat attendu :
VI. Boucle For pour redémarrer des services
Vous avez besoin de redémarrer plusieurs services sur votre serveur Linux ? Vous pouvez utiliser un script Bash pour automatiser cette opération ! Ceci vous évitera d'enchainer les commandes manuellement.
Imaginons que nous souhaitons redémarrer les services "ssh" et "apache2", nous allons déclarer un tableau avec les noms des services :
services=("ssh" "apache2")
Puis, à l'aide d'une boucle For, nous allons parcourir cette liste de service pour effectuer le redémarrage via systemctl. Pour itérer sur tous les éléments d'un tableau en Bash, nous devons utiliser la syntaxe "${services[@]}".
#!/bin/bash
services=("ssh" "apache2")
for service in ${services[@]}
do
echo "Le service $service va être redémarré"
systemctl restart $service
done
Notez que pour exécuter ce script Bash, il faudra préfixer l'appel par "sudo" car le redémarrage d'un service nécessite des privilèges élevés.
sudo ./script.sh
Finalement, quelques secondes plus tard, notre script a bien effectué le redémarrage des services.
VII. Boucle For pour vérifier l'état des services
Pour finir, nous allons coupler l'utilisation des boucles For avec une structure conditionnelle If et Else. Nous allons définir une liste de services, comme dans l'exemple précédent, et préciser si le service est actif ou inactif.
La boucle For sera utilisée pour itérer sur l'ensemble des éléments du tableau, tandis que la structure conditionnelle sera utile pour évaluer l'état du service et indiquer son état. Pour chaque service, le script utilise la commande "systemctl is-active" pour vérifier si le service est actif et affiche le résultat.
Voici le code du script :
!/bin/bash
services=("ssh" "apache2")
for service in ${services[@]}
do
echo "Vérification de l'état du service $service"
if systemctl is-active --quiet $service
then
echo "Le service $service est actif."
else
echo "Le service $service est inactif."
fi
done
Donc, dans le cas où le service ssh est inactif et que le service apache2 est actif, nous obtenons le résultat suivant :
Vérification de l'état du service ssh
Le service ssh est inactif.
Vérification de l'état du service apache2
Le service apache2 est actif.
Remarque : le fait d'ajouter l'instruction "break" dans le bloc "if" permettrait d'arrêter l'exécution de la boucle, si une certaine condition est vérifiée.
VIII. Conclusion
Désormais, vous devriez être en mesure d'écrire vos premières boucles For dans vos scripts Bash sous Linux ! Une notion à connaître pour automatiser les tâches répétitives en Bash. Si vous désirez des exemples supplémentaires ou que vous avez besoin d'aide, n'hésitez pas à poster un commentaire ou à venir échanger sur notre serveur Discord.
Pour approfondir le sujet, vous pouvez consulter nos tutoriels Bash en utilisant le lien ci-dessous :
D'autres tutoriels sur Bash seront publiés par la suite sur IT-Connect !