Aller au menu - Aller au contenu

Icône Les boucles

Mise à jour : 20/11/2011
Difficulté : Difficile Difficile Creative Commons BY-NC-SA
73 501 visites depuis 7 jours , dont 662 sur ce chapitre , classé 6/777
Nous allons découvrir dans ce chapitre un autre élément de base de tous les langages : les boucles. Ces structures permettent de répéter autant de fois que nécessaire une partie du code. En bash, on n'y échappe pas !

Les consignes sont les mêmes que pour le chapitre sur les conditions : il faut être vigilant sur la syntaxe. Un espace de trop ou de moins, un oubli d'un caractère spécial, et plus rien ne marche. Soyez donc très rigoureux lorsque vous codez !

Si vous suivez cette simple règle, vous n'aurez pas de problème. :)
Sommaire du chapitre :
Icône du chapitre
Chapitre précédent Sommaire Chapitre suivant

while : boucler "tant que"

Le type de boucle que l'on rencontre le plus couramment en bash est le while.

Le principe est de faire un code qui ressemble à ceci :

Citation

TANT QUE test
FAIRE
------> effectuer_une_action
RECOMMENCER


En bash, on l'écrit comme ceci :

Code : Bash
1
2
3
4
while [ test ]
do
	echo 'Action en boucle'
done


Il est aussi possible, comme pour le if, d'assembler les 2 premières lignes en 1, à condition de mettre un point-virgule :
while [ test ]; do
echo 'Action en boucle'
done


On va demander à l'utilisateur de dire "oui", et répéter cette action tant que l'utilisateur n'a pas fait ce qu'on voulait. On va créer un script boucles.sh pour l'occasion :

Code : Bash
1
2
3
4
5
6
#!/bin/bash

while [ -z $reponse ] || [ $reponse != 'oui' ]
do
	read -p 'Dites oui : ' reponse
done


On fait 2 tests :
  • Est-ce que $reponse est vide ?
  • Est-ce que $reponse est différent de "oui" ?


Comme il s'agit d'un OU (||), tant que l'un des 2 tests est vrai, on recommence la boucle. La boucle pourrait se traduire par : "Tant que la réponse est vide ou que la réponse est différente de oui".
On est obligé de vérifier d'abord si la variable n'est pas vide, car sinon le second test plante (essayez, vous verrez).

Essayons ce script :

Code : Console
Dites oui : euh
Dites oui : non
Dites oui : bon
Dites oui : oui


Comme vous pouvez le voir, il ne s'arrête que lorsqu'on a tapé oui !

Il existe aussi le mot-clé until, qui est l'exact inverse de while. Il signifie "Jusqu'à ce que".
Remplacez juste "while" par "until" dans le code précédent pour l'essayer.

for : boucler sur une liste de valeurs

Avertissement pour ceux qui ont déjà fait de la programmation : le "for" en bash ne se comporte pas de la même manière que le for auquel vous êtes habitués dans un autre langage, comme le C ou le PHP. Lisez donc attentivement.


Parcourir une liste de valeurs



La boucle "for" permet de parcourir une liste de valeurs, et de boucler autant de fois qu'il n'y a de valeurs.

Concrètement, la forme d'un for est la suivante :

Citation
POUR variable PRENANT valeur1 valeur2 valeur3
FAIRE
------> effectuer_une_action
VALEUR_SUIVANTE


La "variable" va prendre successivement les valeurs "valeur1", "valeur2", "valeur3". La boucle va donc être exécutée 3 fois, et à chaque fois la variable vaudra une nouvelle valeur de la liste.

En bash, la boucle for s'écrit comme ceci :

Code : Bash
1
2
3
4
5
6
#!/bin/bash

for variable in 'valeur1' 'valeur2' 'valeur3'
do
	echo "La variable vaut $variable"
done


Ce qui donne, si on l'exécute :

Code : Console
La variable vaut valeur1
La variable vaut valeur2
La variable vaut valeur3


Vous pouvez donc vous servir du for pour faire une boucle sur une liste de valeurs que vous définissez :

Code : Bash
1
2
3
4
5
6
#!/bin/bash

for animal in 'chien' 'souris' 'moineau'
do
        echo "Animal en cours d'analyse : $animal"
done


Code : Console
Animal en cours d'analyse : chien
Animal en cours d'analyse : souris
Animal en cours d'analyse : moineau


Toutefois, la liste de valeurs n'a pas besoin d'être définie directement dans le code. On peut utiliser une variable :

Code : Bash
1
2
3
4
5
6
7
8
#!/bin/bash

liste_fichiers=`ls`

for fichier in $liste_fichiers
do
	echo "Fichier trouvé : $fichier"
done


Ce script liste tous les fichiers trouvés dans le répertoire actuel :

Code : Console
Fichier trouvé : boucles.sh
Fichier trouvé : conditions.sh
Fichier trouvé : variables.sh


On pourrait faire un code plus court, sans passer par une variable $liste_fichiers, en écrivant :
Code : Bash
1
2
3
4
5
6
#!/bin/bash

for fichier in `ls`
do
	echo "Fichier trouvé : $fichier"
done


Bien entendu, ici on ne fait qu'afficher le nom du fichier, ce qui n'est pas très amusant ni très utile. On pourrait se servir de notre script pour renommer chacun des fichiers du répertoire actuel en leur ajoutant un suffixe -old par exemple :

Code : Bash
1
2
3
4
5
6
#!/bin/bash

for fichier in `ls`
do
	mv $fichier $fichier-old
done


Essayons de voir si l'exécution du script renomme bien tous les fichiers :
Code : Console
$ ls
boucles.sh  conditions.sh  variables.sh
$ ./boucles.sh 
$ ls
boucles.sh-old  conditions.sh-old  variables.sh-old


A vous de jouer ! Essayez de créer un script multirenommage.sh basé sur ce principe qui va rajouter le préfixe -old... uniquement aux fichiers qui correspondent au paramètre envoyé par l'utilisateur !

Code : Console
./multirenommage.sh *.txt


Si aucun paramètre n'est envoyé, vous demanderez à l'utilisateur de saisir le nom des fichiers à renommer avec read.


Un for plus classique



Pour les habitués d'autres langages de programmation, le "for" est une boucle qui permet de faire prendre à une variable une suite de nombres.

En bash, comme on l'a vu, le "for" permet de parcourir une liste de valeurs. Toutefois, en trichant un peu à l'aide de la commande seq, il est possible de simuler un for classique :

Code : Bash
1
2
3
4
5
#!/bin/bash
for i in `seq 1 10`;
do
	echo $i
done


Explication : seq génère tous les nombres allant du premier paramètre au dernier paramètre, donc 1 2 3 4 5 6 7 8 9 10 :

Code : Console
1
2
3
4
5
6
7
8
9
10


Si vous le voulez, vous pouvez changer le pas et avancer de 2 en 2 par exemple. Dans ce cas, il faut écrire seq 1 2 10 pour aller de 1 à 10 en avançant de 2 en 2. Cela va donc générer les nombres 1 3 5 7 9. :)

Q.C.M.

Est-ce que cette syntaxe est correcte ?


Code : Bash
1
2
3
4
while [test]
do
	echo 'Action en boucle'
done
Quelle est la différence entre while et until ?
Quelle est l'erreur de ce code ?


Code : Bash
1
2
3
4
5
6
#!/bin/bash

for $fichier in `ls`
do
	echo "Fichier trouvé : $fichier"
done

Statistiques de réponses au QCM

Vous connaissez maintenant le fonctionnement des boucles en bash, ce qui va vous être indispensable pour la réalisation de futurs scripts !

En parlant de scripts, je pense qu'il est temps que l'on s'entraîne ensemble sur un vrai script dans un TP. En effet, vous savez faire des choses assez poussées sans le savoir. Il est temps de découvrir un peu ce que le bash a dans le ventre. :)
Chapitre précédent Sommaire Chapitre suivant

Partager

10 commentaires pour "Les boucles"
Note moyenne : 3.81 / 4 (995 votes)
Pseudo Commentaire
Hors ligne djibril013 # Posté le 28/11/2009 à 21:53:18

Bonjour,

je souhaiterais automatiser la création de fichier .deb
J'en ai 120 à faire donc c'est un long a faire un par un.

Comment faire svp?

j'ai fais ca mais ca ne marche pas:

#!/bin/bash
# créer des paquets debian à partir de dossier

for i in "$@"
do
DOSSIER=$1
cd $DOSSIER
echo "Nom de l'archive"
read NOM
dpkg-deb -b $NOM
done
Hors ligne Agmenor # Posté le 23/12/2009 à 17:01:03
Ubuntéro pérégrinant
Avatar

Avis : Très bon

Ville : Palaiseau
Pays : France métropolitaine
Études : Polytechnique

Hello!
Ouah! Je suis presque arrivé au bout du tuto. Il est vraiment superbe et m'a fait apprendre tout ce que je voulais sur Linux, et même plus.
À propos de cette page, j'ai fait l'exercice proposé multirenommage.sh. Mon script semble fonctionner, mais j'ai juste encore un écueil quant aux fichiers dont le nom contient un espace. Il servira peut-être de solution à un autre zéro?
Merci pour le tutoriel et bonne programmation!

Code : Bash
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
#!/bin/bash
#Rajouter le suffixe "-old" aux noms de fichiers.

#Si l'utilisateur n'a pas ajouté d'argument à l'appel du programme.
if [ $# = 0 ]
then
	read -p 'Entrez la liste des fichiers:' liste
	bash multirenommage.sh $liste
fi

#Si l'utilisateur a bien mis des arguments à l'appel du programme.
while [ $# != 0 ]
do
	mv $1 $1-old
	shift
done

Image utilisateur

Image utilisateur
 
Hors ligne yeyain # Posté le 07/01/2010 à 15:47:01

Juste comme sa ton bash la il change, mais y a rien pour lui dire de s'arreter a un moment?! je cherche comment lui dire de s'arreter quand il y a pu de fichier a copier car moi il continue a vouloir modifier des fichier alors qu'il sont tous fait.
Hors ligne blatman100 # Posté le 09/06/2010 à 22:41:56

J'ai dû chercher sur le net pour trouver la solution qui me semble idéale. Elle utilise le terme "$@" qui correspond à l'ensemble des paramètres envoyés.
A partir de ce moment il est très simple de coder le reste. :p
En espérant en avoir aidé certains.
Hors ligne computerman # Posté le 03/07/2011 à 19:01:02

Bonjour,
Je vous propose cette solution pour le multirenommage :

Code : Bash
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
while [ $# -eq 0 ] && [ -z $fichier_a ]
do
  read -p 'saisissez le nom des fichiers à renommer : ' fichier_a
  
done

extension = `find -name "$fichier_a" | cut -d . -f 2`

for fichier in `find -name "$fichier_a" | cut -d . -f 1`

do
  mv $fichier-.$extension $fichier-old-.$extension
done


Dites moi ce que vous pensez.

Voir tous les commentaires