Université Grenoble Alpes DLST
UE INF203 Année 2021-22
INF203 - Exercices semaine 3
Shell : structures de contrôle
Exercice 1 :
Écrire un programme script (en langage shell) choix.sh, qui accepte 3 arguments, et qui affiche soit le
deuxième argument soit le troisième argument, selon que le premier argument est égal à 2 ou à 3.
Que se passe-t-il à l’exécution des commandes suivantes ?
choix.sh 3 bonjour bonsoir
choix.sh bonjour bonsoir
choix.sh 2 bonjour
choix.sh 3 bonsoir
Solution :
if [ $1 -eq 2 ]
then
echo $2
else
echo $3
fi
Exercice 2 :
Écrire un script shell qui affiche le plus grand de ses arguments, en supposant qu’il s’agit d’entiers :
1. dans un premier temps, avec seulement 3 arguments, en vérifiant qu’il n’y en a bien que 3, et unique-
ment avec des structures conditionnelles imbriquées ;
2. puis, à l’aide d’autres structures de contrôle et d’une ou plusieurs variables additionnelles.
Solution :
1. la solution avec les conditionnelles est assez longue
if [ $# -ne 3 ]
then
echo 3 arguments attendus
exit 1
fi
if [ $1 -ge $2 ]
then
if [ $1 -ge $3 ]
then
echo $1
elif [ $3 -ge $2 ]
then
echo $3
else
INF203 - 2021/2022 1 Exos3
echo $2
fi
elif [ $3 -ge $2 ]
then
echo $3
else
echo $2
fi
2. la solution avec une variable intermédiaire qui suit le maximum est plus courte
if [ $# -ne 3 ]
then
echo 3 arguments attendus
exit 1
fi
max=$1
if [ $2 -ge $max ]
then
max=$2
fi
if [ $3 -ge $max ]
then
max=$3
fi
echo $max
Exercice 3 :
— Écrire un fichier de commande qui préfixe par ”rep ” tous les répertoires présents dans le répertoire
courant.
Solution :
for F in *
do
if [ -d $F ]
then
mv $F rep_$F
fi
od
— Écrire un fichier de commande qui efface tous les fichiers exécutables du répertoire courant.
Quel problème se pose si on exécute ce script ? Comment y remédier ?
Solution :
for F in *
do
if [ -f $F -a -x $F -a $F != $0]
then
rm $F
fi
od
— Écrire un fichier de commandes qui prend comme unique argument un nom de répertoire, puis compte
INF203 - 2021/2022 2 Exos3
et affiche le nombre de fichiers accessibles en lecture dans ce répertoire.
Solution :
if [ $# -ne 1 -o ! -d "$1" ]
then
echo usage $0 repertoire
exit 1
fi
cpt=0
for i in $1/*
do
if [ -r $i ]
then
cpt=$(expr $cpt + 1)
fi
done
echo $cpt
— Même question, mais votre script doit accepter un nombre quelconque de répertoires en argument, et
faire ce traitement dans chacun des répertoires.
Solution :
Même chose mais avec une boucle for d in $* et $d remplace $1.
On peut compter le nombre de fichiers dans chaque répertoire et le nombre total.
Exercice 4 :
Écrire un fichier de commande, prenant un argument N sur la ligne de commandes, qui calcule et affiche :
— la somme des N premiers entiers ;
— la liste des entiers premiers de l’intervalle [0; N ].
(ça n’a bien sûr pas vraiment d’intérêt en shell...)
Solution :
i=0
somme=0
while [ $i -le $1 ]
do
somme=$(expr $somme + $i)
i=$(expr $i + 1)
done
echo $somme
Exercice 5 :
On souhaite écrire un script compare.sh permettant de savoir quel répertoire parmi les deux passés en
paramètre contient le plus de fichiers ordinaires exécutables. Par exemple,
toto$ ./compare.sh rep1 rep2
donnera l’affichage suivant :
rep1 contient plus d’executables que rep2
1. Écrivez le si permettant de vérifier si le nombre de paramètres est correct. Dans le cas contraire,
vous afficherez le message d’erreur adéquat, puis retournerez le code d’erreur 1.
INF203 - 2021/2022 3 Exos3
2. Vérifiez avec un seul si que les deux paramètres sont des répertoires. Dans le cas contraire, vous
afficherez le message d’erreur adéquat, puis retournerez le code d’erreur 2.
3. Donnez la condition permettant de tester si un fichier FICH est ordinaire et exécutable.
4. Donnez le code de la fonction compte() qui écrit dans la variable res le nombre de fichiers ordi-
naires exécutables se trouvant dans le répertoire dont le nom est passé en paramètre.
5. En utilisant les codes précédents, donnez le code du script compare.sh.
Solution :
#!/bin/bash
if [ $# -ne 2 ]
then
echo usage : $0 rep1 rep2
exit 1
fi
if [ ! -d $1 -o ! -d $2 ]
then
echo usage : $0 rep1 rep2
exit 2
fi
compte()
{
res=0
for fich in $1/*
do
if [ -f $fich -a -x $fich ]
then
res=$(expr $res + 1)
fi
done
}
compte $1
nb1=$res
compte $2
nb2=$res
if [ $nb1 -gt $nb2 ]
then
echo $1 contient plus d\’executables que $2
elif [ $nb1 -lt $nb2 ]
then
echo $2 contient plus d\’executables que $1
else
echo $2 contient autant d\’executables que $1
fi
Exercice 6 :
1. Expliquer ligne à ligne le contenu de ce fichier script ./mystere.sh donné ci-dessous :
#!/bin/bash
if [ $# -ne 1 ]
then
echo usage : $0 path
INF203 - 2021/2022 4 Exos3
exit 1
fi
if [ ! -d ~/sauv ]
then
mkdir ~/sauv
fi
for i in $(ls $1/?*[0-9]*.txt)
do
cp $1/$i ~/sauv
done
exit 0
2. Quelle est la valeur de ”$ ?” après qu’un utilisateur a tapé ./mystere.sh
3. Quelle est le contenu du répertoire sauv après l’exécution des commandes suivantes :
> ls
10.txt 3.txt 6.txt 9.txt fich2.txt fich5.txt fich8.txt
1.txt 4.txt 7.txt fich10.txt fich3.txt fich6.txt fich9.txt
2.txt 5.txt 8.txt fich1.txt fich4.txt fich7.txt mystere.sh
> ./mystere.sh .
4. Quel est le contenu du répertoire courant après que l’utilisateur a tapé la commande rm *[0-5][!0-5]*
Solution :
1. Le script vérifie que l’appel reçoit un et un seul argument ; il crée alors le dossier sauv dans le
répertoire racine de l’utilisateur si ce dossier n’existe pas ; on copie alors tout les fichiers d’extension
txt composé d’au moins une lettre suivie de 0 à plusieurs chiffres du dossier donné en argument dans
le répertoire sauv.
2. La valeur de $? est 1.
3. Le répertoire sauv contient l’ensemble des fichiers ficheX.txt ainsi que le fichier 10.txt.
4. Le répertoire contient ici seulement les fichiers contenant un caractère de 0 à 5 suivi par au moins un
caractère qui n’est pas 0 à 5.
INF203 - 2021/2022 5 Exos3