OS6Ecriture de scripts bash sous Linux

 

display:condition;

Table des matières

Les « shells » Linux

Généralités

Script shell

Le Bourne Shell (bash)

Lancement

Terminaison

Les variables shell

Définir / modifier et afficher une variable

Les variables arguments

Définition

Plus de 9 variables de position

Exemple

Les variables spéciales

Variable tableau

Définition

Utilisations :

Les méta-caractères

Le « quoting »

Encadrement par guillemets

Encadrement par des quotes

Encadrement par des backquotes

Déspécialisation ponctuelle

Langage de programmation

Utiliser des variables numériques

Réaliser des calculs

Tester si une variable est numérique

Tests

Test « if »

Deux syntaxes possibles

Conditions de test textuelles

Conditions de test numériques – forme 1

Conditions de test numériques – forme 2

Conditions de test sur expression

Conditions de test sur fichiers

Test « case »

Syntaxe

Boucles

Boucle « for »

Première syntaxe

Deuxième syntaxe

Boucle « while »

Syntaxe

Exemple

Boucle « until »

Lire le clavier ou un fichier

Lire le clavier

Réaliser un menu

Syntaxe

Exemple

Lire un fichier ligne par ligne

Méthode 1

Méthode 2

Lire un fichier mot par mot

Briser / poursuivre les boucles

Sources

 

Les « shells » Linux

Généralités

Les shells sont des interpréteurs de commnde1 évolués pourvus d'un langage de programmation  puissant.

Il servent trois objectifs :

  1. 1.permettre à l'utilisateur de lancer simplement au clavier l'exécution des programmes stockés dans la mémoire de masse (les « commandes externes »).  

  2. 2.autoriser l'utilisateur à personnaliser sa session de travail par le biais de variables d'environnement.  

  3. 3.donner la possibilité à l'utilisateur d'écrire et de faire exécuter  de véritables programmes nommés « scripts shell ». Ces scripts  réalisent des enchaînements conditionnels de commandes permettant l'automatisation de traitements complexes. 

Pour simplifier Linux fournit deux shells :

  1. 1.le « bash »ou « bourne shell », shell officiel « GNU », qui est utilisé majoritairement pour écrire les scripts 

  2. 2.le « csh » – ou « C shell », et le « tcsh » qui est un « csh » plus rapide et plus puissant. Ce shell propose un langage de programmation très proche du langage C. 

Lorsqu'un utilisateur lance ou termine un shell certain scripts (voir ci-après) sont exécutés automatiquement par le shell (s'ils existent). Ces fichiers sont stockés dans le sous-répertoire personnel (« ~ ») de l'utilisateur ou dans le sous-répertoire « /etc ».

Un shell peut être lancé dans différents modes de connexion :

  1. 1.« login » : le shell est lancé lorsqu'un utilisateur se connecte au système, 

  2. 2.« interactif » : le shell est lancé pour que l'utilisateur puisse entrer des commandes texte au clavier, 

  3. 3.« non-interactif » : le shell est lancé pour exécuter un script. 

Script shell

Un script shell est un fichier texte contenant un programme pouvant être interprété (~ exécuté) par un shell.

Pour cela, il doit posséder l’attribut « x » d’exécution. On peut aussi lancer un script shell qui n'a pas l'attribut « x » en utilisant la commande source.

La première ligne d'un fichier script peut préciser par quel type de shell il doit être exécuté.

Exemple : pour forcer l'exécution du script par un shell « csh », sa première ligne doit être :
#!/bin/csh

Note : par défaut sous Linux, un script shell est exécuté par le « Bourne Shell » (voir ci-dessous)

Le Bourne Shell (bash)

Lancement

Par défaut lorsqu'un utilisateur lance un terminal il lance l'exécution d'un bash en mode « interactif ».

On peut également dans un terminal existant (exécutant par exemple un autre shell comme le « csh ») – ou même un autre bash) lancer un bash également en mode « interactif » en entrant la commande bash .

Si on souhaite lancer l'exécution en arrière-plan d'un script – nommé par exemple « riri » (mode « non interactif »), on peut utiliser la commande suivante : bash riri &  

Au lancement les scripts exécutés automatiquement dépendent du mode utilisé :

Terminaison

La terminaison d'un bash lancé en mode « interactif » s'effectue lorsque l'utilisateur entre la commande exit

 

En mode « non interactif » le bash se termine lorsque l'exécution du script qu'il interprète est terminée.

 

En mode « login » : le shell exécute le script « ~/.bash_logout » lors de la sortie de session.

Les variables shell

Le bash utilise un grand nombre de variables pour son usage propre et permet également d'en définir de nouvelles.

Ces variables sont constituées d'un doublet (nom, valeur). Par défaut la valeur d'une variable est toujours une chaîne de caractères (bien que bash donne la possibilité de définir et d'utiliser des variables numériques entières).

Les variables sont conservées dans une zone de données associée au processus appelée espace d'environnement.

Pour un processus donné cet espace est scindé en deux parties distinctes :

  1. 1.la première est héritée du processus parent qui a lancé l'exécution du processus courant 

  2. 2.la seconde est propre au processus courant.  

Lorsqu'une nouvelle variable est créée dans un processus donné elle est stockée dans la deuxième partie de l'espace d'environnement.

Ceci signifie qu'elle ne sera transmise à aucun processus lancé à partir du processus courant.

Pour qu’une variable créée dans un shell soit passée aux processus lancés à partir de ce shell il faut utiliser une commande interne spécifique au bash nommée export suivie du nom de la variable

Exemple : exporter la variable nommée « fifi » : export fifi

Définir / modifier et afficher une variable

Une variable est un couple (nom, valeur).

Pour définir une variable, il suffit de déposer une valeur dans cette variable ; pour cela il faut lier le nom de la variable et sa valeur par le signe « = ».

Exemple : pour déposer le texte « coucou » dans la variable « riri » : riri=coucou

ATTENTION : remarquez l'absence indispensable d'espaces autour du signe « = »

La valeur déposée dans la variable ne doit pas comporter d'espaces, dans le cas contraire il faut encadrer cette valeur par des guillemets.

Exemple : pour déposer le texte « coucou c'est moi » dans la variable « riri » : riri="coucou c'est moi" .

Pour afficher ou utiliser une variable il faut utiliser son nom précédé du caractère « $ ».

Exemple : pour afficher à l'écran la valeur de la variable « riri » : echo $riri

Pour modifier une variable on utilise également le signe « = » en plaçant à droite une nouvelle valeur, une expression ou la valeur d'une autre variable

Exemple : pour déposer la valeur de la variable « fifi » dans la variable « riri » : riri=$fifi .

On peut trouver ci-dessous différents cas d'affectation, de modification et d'affichage de variables :

bash$ var1=coucou

bash$ echo $var1

coucou

bash$ echo $VAR1

bash$ var1 =coucou

bash: var1: command not found

bash$ var1= coucou

bash: coucou: command not found

bash$ var1=

bash$ echo $var1

bash$ VAR1=$var1

bash$ echo $VAR1

coucou

bash$ var1=coucou ca va

>

CTRL/C

bash$ var1="coucou ca va"

bash$ echo $var1

coucou ca va

bash$

Les variables arguments

Définition

Les variables arguments sont des variables utilisées à l'intérieur d'un script et dont les valeurs sont positionnées avec les arguments fournis au script lors de son lancement en ligne de commande.

Exemple : le script suivant (nommé « sc ») fournit des informations sur ses arguments de lancement (trace d'exécution à suivre) :

echo $#

echo $0 $1 $2

echo $*

bash$ sc coucou mon ami

3

sc coucou mon

sc coucou mon ami

bash$  

Plus de 9 variables de position

S'il existe plus de 9 variables de position, on accède aux valeurs des arguments supplémentaires en utilisant la commande shell interne shift . L'effet de cette commande est d'effectuer un décalage des valeurs de variables en partant de la variable « 9 ».

Après la première exécution de « shift » la variable « 0 » contient la valeur de la variable « 1 », la « 2 » celle de la « 3 », et ainsi

de suite jusqu'à la « 9 » qui est alors positionnée avec la valeur du 10ème argument.

Exemple

Le script ci-dessous :

  1. 1.effectue un premier affichage des variables de position qui lui sont passées, 

  2. 2.puis appelle la commande shift et réaffiche le contenu des variables de position.  

echo "valeurs des 9 premiers arguments"

echo $1 $2 $3 $4 $5 $6 $7 $8 $9

echo "Premier décalage"

shift

echo "nouvelles valeurs des 9 premiers arguments"

echo $1 $2 $3 $4 $5 $6 $7 $8 $9

Les traces d'exécution sont les suivantes :

bash$ ./script1 a b c d e f g h i j

valeurs des 9 premiers arguments

a b c d e f g h i

Premier décalage

nouvelles valeurs des 9 premiers arguments

b c d e f g h i j

bash$

Les variables spéciales

Elles sont trois :

Variable tableau

Définition

Une variable tableau est reconnaissable au crochets droits (« [ » et « ] ») qui suivent le nom de la variable.

L'expression à l'intérieur des crochets indique le numéro de la case du tableau concernée.

Utilisations :

Les méta-caractères

Les méta-caractères sont des caractères spéciaux qui possèdent une signification précise pour le bash.

Ce document a déjà introduit l'un de ces caractères : le caractère « $ » qui signifie « valeur de » lorsqu'il placé devant un nom de variable. Il en existe bien d'autres ; les plus simples sont présentés ci-après.

Le « quoting »

Le quoting consiste à encadrer des chaînes de caractères par :

  1. 1.des guillemets (« " »),  

  2. 2.des « quotes » (« ' » – touche 4'{ ) 

  3. 3.des « backquotes » («`» – touche 7è` ) 

Encadrement par guillemets

Exemple :
bash$ toto=bernard
bash
$ echo "ca va $toto"
ca va bernard
bash
$ echo "coucou 'ca va'"
coucou 'ca va'
bash$

Encadrement par des quotes

Exemple :
bash$ toto=bernard
bash
$ echo "ca va '$toto'"
ca va $toto
bash
$ echo 'coucou "ca va"'
coucou "ca va"
bash$

Note : remarquez que cette fois « $toto » n'a pas été remplacé par la valeur de toto.

Encadrement par des backquotes

Permet d'évaluer, c'est à dire de récupérer, le résultat de l'exécution d'une commande ou d'un script.

Exemple : on souhaite afficher le sous-répertoire personnel de l'utilisateur précédé d'un commentaire (utilisation de la commande pwd ):
bash$ echo "rep = `pwd`"
rep = /home/albert
bash
$

Déspécialisation ponctuelle

Elle est réalisée par le caractère « slash » (« \ »).

 

Lorsque le slash est placé devant un caractère comme un guillemet, une quote, une backquote ... ou un slash, ce caractère perd sa signification spéciale et est affiché comme un caractère « normal ».

Exemple :
bash$ echo "ca va \"toto\""
ca va
"toto"
bash
$ echo \toto
toto
bash$ echo \\toto
\toto
bash$

Langage de programmation

Le langage de programmation du bash utilise les commandes « internes » et « externes » ainsi que des boucles itératives ou décisionnelles afin de réaliser de véritables programmes.

C'est l'outil favori de l'administrateur Linux.

Utiliser des variables numériques

Réaliser des calculs

Nous avons vu plus haut que le contenu d'une variable shell est considéré par défaut comme du texte ; que faire dans ce cas pour effectuer des calculs dans un script shell ?

On peut « transformer » le contenu d'une variable contenant un nombre exprimé sous forme textuelle en une « vraie » valeur numérique en utilisant :

L'exemple ci-dessous permet d'illustrer ce qui se passe dans différents cas de figure.

Exemple :
bash$ a=1
bash$ a=$a+1
bash$ echo $a
1+1
bash$ a=1
bash$ a=$(($a+1))
bash$ echo $a
2
bash$ a=1
bash$ let "a=$a + 1"
bash$ echo $a
2
bash$

Tester si une variable est numérique

Il n'existe pas d'opérateur ou de fonction native dans le bash pour tester si une variable est numérique ou pas.

Le script suivant indique le code à utiliser (à suivre les traces d'exécution dans différents cas ; la variable testée est celle passée en argument au script) :

if echo "$1" | grep -q -E '^[0-9]*[,]?[0-9]*$'

then

  echo "$1 numérique"

else

  echo "$1 non numérique"

fi

 

bash$ ./sc 1.04

1.04 non numérique

bash$ ./sc 1,04

1,04 numérique

bash$ ./sc 0,45

0,45 numérique

bash$ ./sc 0,45a

0,45a non numérique

bash$ ./sc 1.2

1.2 non numérique

Tests

Test « if »

Un test if permet de vérifier si une condition est vérifiée et d'exécuter un bloc d'instructions si c'est le cas (et éventuellement un autre bloc dans le cas contraire)

Note 1 : sous Linux quand une commande est réussie elle retourne la valeur « 0 », sinon elle retourne une valeur différente de « 0 ». Un test réussi se comporte de la même manière.

Note 2 : le résultat d'un test est disponible juste après l'exécution du test dans la variable spéciale « $ ? »

Deux syntaxes possibles

if condition

then instructions_si_condition_vraie

fi

ou

if condition

then instructions_si_condition_vraie

else instructions_si_condition_fausse

fi

Pour simplifier, la condition de test peut être exprimée :

ATTENTION : dans le cas où les accolades sont utilisées, un espace doit absolument séparer les accolades du contenu effectif de la condition.

Conditions de test textuelles

« c1 », « c2 » peuvent être des variables contenant du texte ou des chaînes constantes ; « c » est une variable contenant du texte :

Exemple : on donne ci-après le contenu d'un fichier script nommé « sc » et de son exécution :
c1=coucou
c2=cava
if [
$c1 != $c2 ]
then
 echo différentes
else
 echo pareilles
fi

bash$ sc
différentes
bash$

Conditions de test numériques – forme 1

« n1 » et « n2 » contiennent des valeurs numériques.

Exemple : on donne ci-après le contenu d'un fichier script nommé « sc » et de son exécution :

n1=1
n2=2
if [
$n1 -le $n2 ]
then
echo
"n1 <= n2"
else
echo
"n1 > n2"
fi

bash$ sc
n1 <= n2
bash$

Conditions de test numériques – forme 2

On peut également utiliser l'opérateur d'évaluation numérique « ((...)) » en utilisant les opérateurs « classiques » de comparaison numériques : « > », « < », « >= » et « <= ».

Exemple : on donne ci-après le contenu d'un fichier script nommé « sc » et de son exécution :

n1=1
n2=2
if
(($n1 <= $n2))
then
 echo
"n1 <= n2"
else
 echo
"n1 > n2"
fi

bash$ sc
n1 <= n2
bash$

Conditions de test sur expression

« e », « e1 » et « e2 » sont des expressions composées d'instructions, « v » est une variable.

Conditions de test sur fichiers

« file », « file1 » et « file2 » sont des noms de fichier.

Exemple : le script suivant fournit un grand nombre d'informations sur le fichier dont le nom lui est passé en argument :

if [ -e $1 ]
then
 echo "Le fichier $1 est :"
 if
[ -f $1 ]
 then
     echo "un fichier normal"
     if
[ -s $1 ]
     then
         echo "taille > à 0"
     fi
     if
[ -x $1 ]
     then
         echo "executable"
     fi
 fi
 if
[ -d $1 ]
 then
   echo "un repertoire"
 fi
 if
[ -r $1 ]
 then
   echo "autorise en lecture"
 fi
 if
[ -w $1 ]
 then
   echo "autorise en écriture"
 
fi
else
   echo "Le fichier n'existe pas"
fi

Test « case »

Ce type de test cherche à comparer une expression avec un jeu de valeurs.

Syntaxe

case expression in

exp1 ) liste d'instructions 1;;

exp2 ) liste d'instructions 2;;

...

* )  liste d'instructions ;;

esac

Note 1 : souvent expression sera une simple valeur de variable

Note 2 : « exp1 », « exp2 », etc. sont des valeurs pouvant être prises par expression.

Note 3 : liste d'instructions est une suite d'instructions séparées par le caractère point-virgule « ; »

Cette boucle s'interprète de la manière suivante :

Note : la ligne de traitement par défaut (qui commence par « *) » est optionnelle.

Exemple : le script suivant lit un mot entré sur le clavier (à l'aide la commande « read ») et reconnaît le mot « chien » et le mot « carotte » en affichant s'il s'agit d'un animal ou d'un végétal ; s'il ne reconnaît pas le mot il affiche « inconnu ». :
echo "Entrez un mot"
read var
case $var in
 chien) echo animal ;;
 carotte) echo vegetal ;;
 *) echo inconnu ;;
esac

Boucles

Boucle « for »

Cette boucle permet de limiter à une valeur connue à l'avance le nombre de boucles (le nombre de boucles est donc majoré).

Première syntaxe

Cette syntaxe est adaptée au parcours d'une liste de valeurs.

for variable in liste_valeurs

do

    liste instructions

done

Exemple : le script suivant affiche les arguments qui lui sont fournis lors de son lancement (suivi d'une trace d'exécution) :
for i in "$@"
do
 echo "$i"
done

bash$ sc "coucou ca va" toto
coucou ca va
toto
bash$

Note 1 : si la première ligne du script avait été « for i in $@ » la trace d'exécution aurait été :
bash$ sc "coucou ca va" toto
coucou
ca
va
toto
bash$

Note 2 : si la première ligne du script avait été « for i in "$*" » la trace d'exécution aurait été :
bash$ sc "coucou ca va" toto
coucou ca va toto
bash$

Deuxième syntaxe

Cette syntaxe est mieux adaptée à la réalisation d'un certain nombre de boucles.

for (( exp1 ; exp2 ; e3 ))

do

    liste instructions

done

Note : exp1 », « exp2 » et « exp3 » sont des expressions arithmétiques .

La boucle :

Exemple : le script suivant affiche les trois nombres qui suivent l'argument qui lui est fourni lors de son lancement (suivi d'une trace d'exécution) :
for ((i=$1 ; $1+3 - $i ; i++))
do
 echo $(($i + 1))
done


bash$ sc
5
6
7
8
bash$

Boucle « while »

Le nombre de boucles réalisé dans une boucle « while » n'est pas majoré ; la boucle s'exécute TANT QU'une condition « booléenne » n'est pas remplie !

Syntaxe

while condition

do

    liste instructions

done

Exemple

Le script suivant vous aide à deviner un nombre choisi au hasard dans ce script :

g=$(($RANDOM % 100))

echo "nb entre 0 et 100 ? :"

read i

max=100

min=0

while [ $i -ne $g ]

do

  if (($i > $g))

  then

    if (($i < $max));

    then

      max=$i;

    fi

    m=$(( ($max - $min)/2 + $min))

    if (( $m < $g ))

    then

      echo "nb entre $m et $max ? :"

    else

      echo "nb entre $min et $m ? :"

    fi

  else

    if (($i > $min));

    then

      min=$i;

    fi

    m=$(( ($max - $min)/2 + $min))

    if (( $m < $g ))

    then

      echo "nb entre $m et $max ? :"

    else

      echo "nb entre $min et $m ? :"

    fi

  fi

  read i

done

echo "bravo, le nombre est $g"

Boucle « until »

C'est la boucle complémentaire de « while » dans laquelle la boucle s'exécute JUSQU'A ce que la condition booléenne soit remplie.

Sa syntaxe est identique :

until condition

do

    liste instructions

done

Lire le clavier ou un fichier

Ces opérations sont réalisées par la commande read .

Lire le clavier

Exemple : le script suivant vient lire une valeur au clavier, il la dépose dans une variable puis l'affiche :

read a

echo $a

Réaliser un menu

La commande select permet d'afficher un menu de choix et de récupérer le choix effectué par l'utilisateur.

Syntaxe

select choix in liste_de_choix

do

    liste instructions

done

Exemple

Le script suivant nommé « sc » demande à choisir parmi plusieurs fruits (deux traces d'exécution suivent) :

PS3='fruit ? '

select fruit in pomme orange poire banane

  do

  if [[ -n $fruit ]]; then

    echo $fruit

    break

  else

    echo 'mauvais choix'

  fi

  done

bash$ sc

1) pomme

2) orange

3) poire

4) banane

fruit ? 3

poire

bash$

bash$ sc

1) pomme

2) orange

3) poire

4) banane

fruit ? 9

mauvais choix

fruit ?

Note 1 : la variable PS3 positionnée à « fruit ? » contient l'invite à répondre utilisée par l'instruction « select ».

Note 2 : l'instruction break utilisée dans le script permet de « briser » une boucle « do - « done » dans tous les cas.

Lire un fichier ligne par ligne

Dans les deux méthodes ci-dessous, chaque ligne du fichier est lue et déposée dans variable « ligne », puis affichée.

Méthode 1

On utilise la commande cat , le méta-caractère « pipe » (« | » – touche 6-|) et la boucle while :

cat fichier | while  read ligne

do

  echo $ligne

done

Méthode 2

On utilise la redirection du flux de sortie (« stdout ») avec le méta-caractère « < » et la boucle while :

while read ligne

do

  echo $ligne

done < fichier

Lire un fichier mot par mot

Dans l'exemple ci-dessous, chaque mot du fichier est lu et déposée dans variable « mot », puis affichée.

On utilise pour cela le quoting « ` », la commande cat et la boucle for :

for mot in `cat fichier`

do

  echo $mot

done

Briser / poursuivre les boucles

L'instruction break permet de briser sans condition une boucle « do – done »

L'instruction continue permet de « réinitialiser » une boucle – c'est à dire de revenir directement à l'instruction qui débute la boucle.

Sources

http://www.tldp.org/LDP/Bash-Beginners-Guide/html/Bash-Beginners-Guide.html

http://abs.traduc.org/abs-5.0-fr/index.html

 

1Programme chargé de réaliser l'interface entre l'utilisateur et le système d'exploitation