Fiche 6 2023

Télécharger au format pdf ou txt
Télécharger au format pdf ou txt
Vous êtes sur la page 1sur 5

– TD 6– Scripts BASH –

Lyon 2 / ICOM / L1 informatique / Environnement Informatique et Internet

Didier Puzenat [email protected]

1 Introduction
La séance de TD d’aujourd’hui à deux objectifs :
1. étudier des scripts plus complexes qu’un simple enchaînement de commandes ;
2. faire le second QCM noté (30 minutes).

Si vous n’avez pas terminé cette fiche avant le début du QCM, merci de la terminer chez vous.
Les points abordés dans cette fiche seront évalués dans le QCM de la semaine prochaine.
Dans le TD 3 nous avons vu qu’un script est un fichier texte contenant des commandes. Dans
le présent TD nous allons voir qu’il est possible de faire des scripts plus complexes. Le but de
cet enseignement n’est pas d’apprendre à programmer aussi nous n’allons pas étudier et encore
moins écrire de scripts de plus de quelques lignes. Il est important de bien comprendre ce que
font ces scripts et d’essayer d’anticiper leur comportement avant de les tester, sinon ce TD risque
de ne pas vous être très profitable.

2 Structure de contrôle conditionnelle


Dans la plupart des langages, une structure de contrôle conditionnelle est de la forme :

si expression alors instruction(s)

où expression a une valeur de vérité ; par exemple en Python :


age=8
if (age>=7 and age<=77) :
print ("cette BD est pour vous")

En BASH, l’expression est « remplacée » par l’exécution d’une commande dont la valeur de retour
est utilisée pour décider de la suite du traitement, comme le font les opérateurs d’enchaînement
« && » et « || » déjà vus. À titre d’exemple reprenons sous la forme d’un script BASH avec un if
la question 4 de la section 3 de la fiche de TD 3 (« trouver et tester l’enchaînement de commandes
qui affiche "Le répertoire /root n’est pas accessible" si c’est bien le cas »). Par exemple :

dir=$PWD
if cd /root 2> /dev/null
then
cd $dir
else
echo "Le répertoire /root n’est pas accessible !"
fi
À noter que l’indentation (le fait de décaler le texte après le then) n’est pas prise en compte par
BASH, le seul but est de rendre la structure plus lisible. Nous pouvons compléter le script avec
également un message si le répertoire est accessible :

dir=$PWD
if cd /root 2> /dev/null
then
echo "Le répertoire /root est accessible !"
cd $dir
else
echo "Le répertoire /root n’est pas accessible !"
fi

Par ailleurs, nous avons vu en cours la notion de « paramètres positionnels », pour rappel il s’agit
d’arguments précisés lors de l’appel du script et accessibles dans le script, ainsi $1 correspond
au premier argument, $2 au second, etc. Dans l’exemple précédent, nous pouvons par exemple
passer en argument le répertoire à tester :

dir=$PWD
if cd "$1" 2> /dev/null
then
echo "Le répertoire $1 est accessible !"
cd $dir
else
echo "Le répertoire $1 n’est pas accessible !"
fi

À faire, pour chacun des scripts précédents :


1. taper le script avec un éditeur (par exemple nano), sauver sous le nom testacces ;
2. rendre le script exécutable le cas échéant ;
3. lancer le script en n’oubliant pas le chemin (./testacces), et sans oublier de préciser
l’argument pour le dernier script (par exemple ./testacces /home).

Enfin, notons que plutôt qu’aller à la ligne nous pouvons enchaîner les commandes sur une même
ligne avec « ; » mais ce n’est pas conseillé lorsqu’on débute en BASH ! Par exemple :

dir=$PWD
if cd "$1" 2> /dev/null ; then echo "Le répertoire $1 est accessible !" ; cd $dir
else echo "Le répertoire $1 n’est pas accessible !" ; fi

3 Built-in test command


Une commande interne à l’interpréteur (donc une « built-in ») nommée test est très utile dans
un script, elle permet de comparer des valeurs, mais aussi de faire diverses vérifications sur les
fichiers et répertoires. On peut par exemple utiliser l’opérateur -ge pour « greater or equal » :

test $age -ge 7 && echo "vous êtes assez grand pour lire Tintin"

if test $age -ge 7 ; then echo "vous êtes assez grand pour lire Tintin" ; fi

2
Afin de rendre les scripts plus lisibles – notamment pour un habitué des langages de program-
mation classiques – une syntaxe originale de la commande test est de n’écrire que son argument
encadré par des crochets, par exemple :

[ $age -ge 7 ] && echo "vous êtes assez grand pour lire Tintin"

if [ $age -ge 7 ] ; then echo "vous êtes assez grand pour lire Tintin" ; fi

À faire :
1. lire intégralement le man de test (pour rappel en tapant « man test ») ;
2. déclarer une variable age et lui affecter une valeur (par exemple « age=8 ») ;
3. tester les 4 lignes précédentes (ne pas hésiter à copier-coller) ;
4. recommencer avec d’autres valeurs pour age.

Il est évidemment possible d’utiliser des expressions plus complexes en utilisant les trois opéra-
teurs de base de la logique booléenne (« et » (-a), « ou » (-o) et « non » (!)), par exemple :

[ $age -ge 7 -a $age -le 77 ] && echo "vous avez l’âge de lire Tintin"

Vous vous demandez sans doute pourquoi « $age -ge 7 » et non simplement « $age >= 7 »
comme dans l’exemple Python donné au début de la fiche ? C’est une conséquence de l’absence
de typage, en effet pour le BASH toutes les variables sont des chaînes de caractères, dès lors il
faut un opérateur particulier pour spécifier qu’il faut traiter le contenu comme un entier. Les
opérateurs possibles sont -eq pour « equal », -ne pour « not equal », -lt pour « less than », -le
pour « less or equal », -gt pour « greater than » et -ge pour « greater or equal ».

Il existe de plus de nombreux tests possibles sur les fichiers et répertoires, par exemple l’opérateur
unaire « -d » teste si un répertoire existe :

[ -d "$rep" ] && echo "$rep existe et est un répertoire !"

Quelques opérateurs unaires incontournables :


[ -a fichier ] True si fichier existe ;
[ -d fichier ] True si fichier est un répertoire ;
[ -e fichier ] True si fichier existe (que ce soit un fichier normal ou un répertoire) ;
[ -r fichier ] True si fichier existe et est lisible (droit r) ;
[ -s fichier ] True si fichier existe et n’est pas vide ;
[ -w fichier ] True si fichier existe et peut être modifié (droit w) ;
[ -x fichier ] True si fichier existe et est un fichier exécutable (droit x)
ou un répertoire traversable (droit x).
À faire : réécrire la commande testacces en utilisant un des opérateurs de la liste précédente,
la solution est à la fin de la fiche, section 6.1.
Il existe aussi des opérateurs travaillant sur les chaînes de caractères, par exemple pour tester
si deux chaînes sont identiques :

[ "$(pwd)" == "$HOME" ] && echo "Bienvenue à la maison"

3
Les opérateurs de comparaison principaux sur les chaînes sont :
[ chaîne1 == chaîne2 ] True si les deux chaînes sont identiques ;
[ chaîne1 != chaîne2 ] True si les deux chaînes sont différentes ;
[ chaîne1 < chaîne2 ] True si chaîne1 est alphabétiquement avant chaîne2 ;
[ chaîne1 > chaîne2 ] True si chaîne1 est alphabétiquement après chaîne2 ;
et il est aussi possible de tester si une chaîne est vide :
[ -z chaîne ] True si la chaîne chaîne est vide ;
[ -n chaîne ] True si la chaîne chaîne n’est pas vide.

À faire :
1. donner une ligne de commandes qui affiche un message si on est en 2023, une solution
possible est proposée section 6.2 ;
2. proposer un script qui affiche le titre du roman dans lequel le mot « ballon » apparaît
plus souvent, entre « De la Terre à la Lune » et « Le tour du monde en 80 jours » ; les
fichiers étant disponibles respectivement aux URL suivantes :
https://www.gutenberg.org/files/799/799-0.txt,
https://www.gutenberg.org/cache/epub/800/pg800.txt,
une solution est disponible section 6.3.

4 Pattern matching
Une alternative aux crochets est l’usage de doubles crochets ; le principal intérêt est l’utilisation
d’expressions plus complexes lors de la comparaison de chaînes de caractères, par exemple l’étoile
(*) équivaut à une suite de caractères quelconques (une suite éventuellement vide), le point
d’interrogation (?) représente un et un seul caractère quelconque, etc. On parle de « pattern
matching » ce qui en français pourrait se traduire par « mise en correspondance de formes ».
À faire : tester [[ $(date) == *2023* ]] && echo "on est en 2023" ;
voir section 6.4 si vous n’avez pas de machine pour tester (par exemple si vous révisez chez vous).

5 Affectation des paramètres positionnels et découpage de chaîne


L’usage de la commande set (entrevue en CM) permet d’initialiser les paramètres positionnels
aux arguments de set. À tester :
set a b c ; echo $1 $2 $3 $# (voir section 6.4 si vous n’avez pas de machine pour tester) ;
set $(date) ; echo $4 (voir section 6.4 si vous n’avez pas de machine pour tester).
Comme le montre le dernière exemple, l’usage de la commande set peut évidemment être com-
biné avec les expansions, en l’occurrence l’expansion de commandes – aussi appelée substitution
de commandes – ($(date)). Il est aussi possible de faire une expansion de variables. Pour rappel,
lors d’une expansion de variables, une chaîne non protégée par des guillemets « subit » un décou-
page (en anglais « word spliting ») sur la base d’un ensemble de caractères séparateurs précisés
par la variable IFS pour « Internal Field Separator ». Par défaut, les caractères séparateurs sont
l’espace, la tabulation et le retour à la ligne.

À tester :
toto="/home/jlpicard/mission.txt" ; IFS="/" ; echo "$toto" (solution section 6.4) ;

4
toto="/home/jlpicard/mission.txt" ; IFS="/" ; echo $toto (solution section 6.4) ;
toto="Title: De la Terre à la Lune" ; IFS=":" ; set $toto ; echo $2 (voir 6.4).
Attention, le « word spliting » est uniquement lié à l’expansion de variables ; à tester :
IFS=":" ; set Title: De la Terre à la Lune ; echo $2 (solution section 6.4).

6 Solutions
6.1 Solution pour la commande testacces
if [ -x $1 ]
then echo "Le répertoire $1 est accessible !"
else echo "Le répertoire $1 n’est pas accessible !"
fi

6.2 Test de l’année en cours


[ $(date +%Y) == "2023" ] && echo "on est bien en 2023 !"

Mais évidemment il y a d’autres solutions, par exemple :

date | grep -q 2023 && echo "on est bien en 2023 !"

6.3 Qui a le plus de ballons ?


wget https://www.gutenberg.org/files/799/799-0.txt
wget https://www.gutenberg.org/cache/epub/800/pg800.txt
if [ $(grep -c ballon 799-0.txt) -gt $(grep -c ballon pg800.txt) ]
then echo "De la Terre à la Lune"
else echo "Le tour du monde en 80 jours"
fi

6.4 Affichage des commandes des sections 4 et 5


[[ $(date) == *2023* ]] && echo "on est en 2023" affiche « on est en 2023 » ;
set a b c ; echo $1 $2 $3 $# affiche « a b c 3 » ;
set $(date) ; echo $4 affiche « 2023 » ;
toto="/home/jlpicard/mission.txt"
IFS="/" ; echo "$toto" affiche « /home/jlpicard/mission.txt » ;
toto="/home/jlpicard/mission.txt"
IFS="/" ; echo $toto affiche « home jlpicard mission.txt » ;
toto="Title: De la Terre à la Lune"
IFS=":" ; set $toto ; echo $2 affiche « De la Terre à la Lune » ;
IFS=":" ; set Title: De la Terre à la Lune ; echo $2 affiche « De » ! ! !

Vous aimerez peut-être aussi