Initiation aux shell scripts et Bash

Introduction :

A qui s'adresse cet article ?

 Cet article s'adresse aux débutants qui n'ont aucune notions en scripting Bash, il s'agit d'une initiation, comme l'indique le titre, avec exercices d’entraînement tout à la fin. Les exercices proposés à la fin quant a eux, peuvent aussi servir d'entraînement aux utilisateurs plus avertis.

Les script, c'est quoi ?

Les scripts sont des programmes en langages interprétés : ce sont des fichiers écrit dans des langages qui sont convertit en instructions directement exécutables par la machine au moment de son exécution. On appel ces langages, langages de script.

Ces langages sont parfois interprétés par un shell (nous allons définir ce qu'est un shell par la suite), ce sont des langages qui permet de manipuler les fonctionnalités du système. On associe, d'ailleurs, souvent le langage de script au shell qui l'interprète. C'est le cas de Bash que nous allons traiter dans ce cours.

Les shells qu'est ce que c'est ?

Les Shells sont des interfaces qui servent à communiquer avec le système, elles sont le plus généralement présents dans les systèmes de type Unix. Pour les systèmes Unix, il s'agit d'un interpréteur de commande en mode texte.

Il existe plusieurs shell, sur les systèmes de type Unix, dont les plus connus sont les suivants :


Le Bash est sans doute le shell le plus utilisé aujourd'hui sur les systèmes de type Unix (en particulier pour la plupart des distributions Linux et la génération des Mac OS X) et c'est sur lui que portera ce tutoriel. Vous pouvez néanmoins définir un autre shell par défaut dans votre terminale ou tout simplement en l'utilisant de manière passagère (pour cela il suffit de l'appeler en console, par exemple ksh pour appeler Ksh).

Le shell utilisé par défaut par votre terminal n'influe pas sur l'usage d'un autre shell dans des scripts. Par contre il faut vérifier que le shell que vous souhaitez utilisé dans votre script soit bien présent dans le répertoire /bin. Sinon vous pourrez toujours l'installer.

 

Quelques informations supplémentaires sur Bash ?

Bash signifie Bourne Again SHell. C'est un jeu de mot avec le Bourne shell, le shell original d'Unix sur lequel Bash est majoritairement basé, et de l'anglais born again (né de nouveau ou encore réincarné).

Le Bourne Again Shell est le shell du projet GNU basé principalement sur le Bourne Shell, mais lui apportant de nombreuses améliorations provenant d'autres types de shells, notamment du Korn Shell et du C shell.
qui signifie

Les scripts Bash sont donc des fichiers texte qui contiennent des commandes shell et des instructions de contrôle de type if, while, ... Ils sont directement interprétés par le shell en question et permettent d'automatiser les tâches en console habituelles qui sont souvent des tâches d'administration.

De quoi as t'on besoin pour programmer en Bash ?

Pour développer en Bash, un éditeur de texte quelconque comme Gedit ou Kate suffit. Vous pouvez également (et c'est souvent utile lorsque que vous faites du scripting sans interface graphique) utiliser un éditeur en mode console tel que Nano (pour les utilisateurs débutants), Vim ou Emacs (pour les utilisateurs avertis).

Il faut aussi savoir que connaître les syntaxes des différentes instructions en Bash ne suffit pas à la réalisation d'un script. En effet, il faut connaître un minimum de commandes pour savoir quelles tâches automatiser . Ainsi pour étoffer vos scripts, je vous recommande de visiter la liste des commandes du shell Linux (ou Unix).

I - Les éditeurs de texte en mode console


Comme il a été dit plus haut, il vous faut un éditeur de texte pour coder en Bash. Voici donc quelques éléments utiles qui pourront vous servir à l'utilisation des éditeurs en mode console.


1) L'éditeur vim :

* il est possible que le vim installé sur votre distribution soit un vim restreint proche de l'ancien éditeur vi (avec le paquet vim-tiny) dans ce cas il faut installer le paquet vim pour avoir ce minituto (il est d'ailleurs préférable d'installer ce paquet tout court).

2) L'éditeur Emacs :

Pour aller plus loin avec Emacs, voici quelques tutoriels intéressants :

GNU Emacs : un éditeur de texte très puissant pour Linux (developez.com)
Introduction à l'éditeur de texte Emacs sous linux (developez.com)

3) L'éditeur Nano :
Vous pouvez également aller plus loin avec Nano, pour cela, voici quelques tutos :

II - Création d'un script sous Linux

Votre script est tout simplement un fichier texte dans lequel vous pouvez écrire les commandes que vous voulez exécuter plus rapidement (on parle d'automatiser les tâches habituelles). Des structures sont mise en place afin de contrôler l'exécution de ces commandes à notre guise. Ce fichier doit contenir comme première ligne  (appellée "shebang") :
#!/bin/bash

Rappelons
, que le Bash est principalement une évolution de sh. Ainsi,
il est possible, au stade des connaissances acquise avec ce tutoriel, d'écrire
en première ligne :

#!/bin/sh
Dans le cas ci-dessus, on fait appel au shell sh et non au Bash. C'est parfois préférable pour que votre script soit standard et qu'il fonctionne ainsi sur toutes les plateformes de type Unix qui parfois, ne disposent pas de Bash (ça reste assez rare tout de même).

Faites ensuite chmod +x nom_du_script en console afin de donner des droits d'exécution en console à ce fichier ("NomDuScript" étant le nom de votre fichier, déplacez le fichier sur le terminal pour retrouver son chemin absolu).

Vous pouvez aussi faire chmod u+x nom_du_script si vous ne souhaitez accorder les droits d'exécution qu'à l'utilisateur propriétaire.

Pour exécuter le script, après lui avoir donné les droits d'exécution, il suffit de rentrer le chemin absolu ou tout simplement de faire ./chemin_relatif_du_script (./nom_du_script si vous êtes, via le shell, dans le répertoire ou se situe le script). 

Exemple :
On va prendre l'exemple des commandes echo, man, read et sleep.

Voici le script que cela devrait donner :
#!/bin/bash
# ceci est commentaire
echo "La page du man va s'ouvrir ..." #(1)
read # (2)
man man # (3)
sleep 2 # (4)
(1) Ici echo affichera la ligne "La page du man va s'ouvrir"
(2) read marque une pause jusqu'à ce que l'on appuie sur une touche
(3) man man ouvre une page de manuel sur le manuel en console
(4) sleep 2 marquera deux secondes de pause

Vous faite ensuite chmod +x NomDuScript, et vous pourrez lancer ce script (cible) dans un terminal avec ./NomDuScript. Celui-ci ouvriras la page du man sur le man.


Pourquoi avoir mis sleep à la fin ?

Cette commande est utile pour avoir le temps de lire les messages d'erreurs si jamais la commande précédente ne s'exécute pas correctement ... Par exemple, imaginez que ce script serve à lancer un exécutable, mais que vous ayez déplacé cet exécutable, cette commande vous permettrait d'avoir le temps de lire le message d'erreur avant que le script ne se ferme. Vous auriez aussi pu mettre read à la place, ainsi, le script ne se fermerait pas avant que vous n'appuyez sur une touche ...

III - Les variables :

Les variables en Bash, ne servent pas qu'à désigner une valeur, elle peuvent désigner du texte, une commande Bash, etc. Déclarer une variable en Bash est très simple, il suffit de l'introduire, par une affectation, comme ceci : 

#!/bin/bash
NomDeLaVariable=X #(1)

(1) NomDeLaVariable est ici notre variable qui a pour valeur X

Attention : Il ne faut pas avoir d'espaces de part et d'autres du signe = !

Pour demander le contenu d'une variable, il faut utiliser read comme ceci :
 

#!/bin/bash 
read Variable # saisie de la valeur de la variable
Dans l'exécution, il faut saisir la valeur de la variable puis appuyer sur [ENTER].

Pour l'afficher, il suffit d'utiliser echo comme ceci : 

echo $NomDeLaVariable   #(1)

(1) $ sert ici à afficher le contenue de la varible qui peut être une valeur, du texte (ne pas oublier les guillemets), une commande, etc

Pour exécuter le contenu d'une variable lorsqu'il s'agit d'une commande, il faut utiliser l'expression $ comme ceci :

#!/bin/bash 
Variable=commande_bash # (1)
$Variable # (2)


(1) Ici le contenu de la variable (Variable) est une commande de la console
(2) Ici $ permet ici d'exécuter la commande


Exemple d'application sur les variables :

#!/bin/bash
echo "Quelle commande souhaitez vous exécuter ?"
read Commande # saisie de la commande

$Commande # exécution de la commande
read

Je vous laisse découvrir son exécution

Autres exemples :

#!/bin/bash
Texte=
"La man page du man va s'ouvrir ..."
echo
$Texte # affichage du texte
man man
 
read 

et

#!/bin/bash
echo "écrivez le texte que vous souhaitez afficher"
read Texte # saisie du texte
echo "$Texte" # affichage du texte
read


IV - Les tests (ou conditions) en Bash :

1) Le test if :

Le test if peut s'écrire de deux manière. Voici les deux syntaxes possibles : 

if test $Variable #condition
then # alors
     # vos commandes ici
fi # fin du bloc if (fi = if à l'envers)  

et

if [ $Variable #condition ]  
then # alors
     # vos commandes ici
fi # fin du bloc if  

if signifie si en angales, then signifie alors et fi (if à l'envers) désigne la fin du bloc. La commande test (équivalente aux crochets) permet quant à elle de tester l'expression donnée en paramètre et de renvoyer un booléen au test if. Pour en savoir plus sur les fonctions de test, faites man test en console.

Il est également possible d'utiliser les conditions else (sinon) et elif (de else if qui signifie sinon si) dans le même bloc :

if [ $Variable #condition ]  
then # alors
     # vos commandes ici
elif [ $Variable #condition ]
then
    # vos commandes ici
else
    # vos commandes ici
fi # fin du bloc if  

Attention aux espaces après le [ et avant le ]. Vous remarquerez aussi qu'il n'y a pas de then après le else ...

Certains opérateurs sont toutefois particuliers en Bash, en voici une liste :

Opérateurs Description Exemple
opérateurs de fichiers
-e  test si le fichier existe if [ -e /etc/group ]
-d  test si le fichier  est un répertoire if [ -d /home ]
-f  test si le fichier  est un fichier ordinaire if [ -f ~/fichier ]
-L  test si le fichier  est un lien symbolique if [ -L /bin/sh ]
-r  test si le fichier  est lisible (r) if [ -r /etc/passwd ]
-w  test si le fichier  est modifiable (w) if [ -w /var/log ]
-x  test si le fichier  est exécutable (x) if [ -x /sbin/ifconfig ]
 -nt  test si un fichier est  plus récent qu'un autre  if [ ~/f1 -nt ~/f2 ]
 -ot  test si un fichier est  plus ancien qu'un autre   if [ ~/f1 -ot ~/f2 ]
comparaison entre chaînes
-z  test si la chaine est vide if [ -z "$str" ]
-n  test si la chaine est non vide if [ -n "$str" ]
 =  test si les deux chaînes sont égales if [ "$str" = "chaine" ]
 !=   test si les deux chaînes sont différentes if [ "$str" != "chaine" ]
comparaisons sur des nombres
 -eq  égalité if [ $nb -eq 10 ]
 -ne  inégalité if [ $nb -ne 10 ]
 -lt  infériorité stricte ( < ) if [ $nb -lt 10 ]
 -le  infériorité non stricte ( <=) if [ $nb -le 27 ]
 -gt  supériorité stricte ( > ) if [ $nb -gt 10 ]
 -ge  supériorité non stricte ( >=) if [ $nb -ge 10 ]

Exemple :


On va prendre un exemple : Un script qui vous demande  si vous voulez afficher la man page du man avec 0 et 1 (1= oui, 0= non).
 

#!/bin/bash
echo "Voulez-vous afficher la man page du man ?"
read Variable # saisie de la variable
if test $Variable -eq 1 # si Variable vaut 1
then # alors
    man man
fi # fin du bloc if
read

Voici la deuxième façon d'écrire ce script :

 #!/bin/bash
echo
"Voulez-vous afficher la man page du man ?"
read
Variable # saisie de la variable

if [ $Variable -eq 0 ] # si Variable vaut 1
then # alors
    man gcc
fi # fin du bloc if
read

 
Les deux test peuvent ce traduire par la phrase "si Variable vaut 1, alors affichons la man page du manuel".

2) Le test case :
 
Le test case est analogue au switch en C, il permet d'éviter une longue et fastidieuse succession de blocs if dans certains cas. Voici la syntaxe d'un test case.

read Variable # saisie de la valeur de la variable
case $Variable in
  Valeur1) # (1)
     #Commande 1 ;;
  Valeur2) # (2)
     #Commande 2 ;;
     # ...
  *) # (3)
     # Commande qui s'éxécute par défaut ;;
esac # fin du bloc case

(1) si l'utilisateur choisi la valeur 1, alorsla commande 1 s'exécute
(2) si l'utilisateur choisi la valeur 2, alorsla commande 2 s'exécute
(3) si l'utilisateur choisi autre chose, la commande par défaut s'exécute

N'oubliez pas le esac (case à l'envers) pour marquer la fin du bloc case. 

Exemple : 

#!/bin/bash
echo "=== Menu === "
echo "1. Royal Cheese  "
echo "2. Mc Deluxe   "
echo "3. Filet-o-Fish "
echo "4. Big Mac "
echo "Votre choix ?"
read choixMenu # saisie de la valeur de la variable
case $choixMenu in
  1) 
   echo "Vous avez choisi le Royal Cheese. Bon choix ! " ;;
  2)
   echo "Vous avez choisi le Mc Deluxe. Berk, trop de sauce..." ;;
  3) 
   echo "Hum pas mal mais c'est bien petit  :( " ;;
  4)
   echo "Vous avez choisi le Big Mac. Vous devez avoir tres faim !";;
   *)  
   echo "Vous n'avez pas rentre un nombre correct. Vous ne mangerez rien du tout !" ;;
esac # fin du bloc case
echo "Appuyez sur une touche pour continuer ..."
read

V - Les boucles : 


Les boucles permettent de répéter une ou plusieurs
opérations tant qu'une condition reste validée.
 

1) Le boucle while  :

 
Voici comment se construit une boucle while :

while [ #condition ]
do
  # instructions à répéter
done

Et voici la deuxième syntaxe possible :

while test #condition 
do
  # instructions à répéter
done
 

Exemple :

On veut créer une boucle qui répète "vive le Bash !" tant que la valeur d'une variable ne vaut pas 0.

Voici les deux solutions possibles :

#!/bin/bash
quitter=1
while [  $quitter -ne 0   ]
do
   echo "Appuyez sur 0 pour quitter ..."
   read quitter
   echo "vive le Bash !"
done
echo "bye !"
read
  


voici la deuxième manière d'écrire ce script :

#!/bin/bash
quitter=1
while test $quitter -ne 0
do
    echo "Appuyez sur 0 pour quitter ..."
    read quitter
    echo "vive le Bash !"
done
echo "bye !"
read

Autre exemple :  

exemple inverse du précédant (on répète la phrase "vive le bash !"
tant qu'une variable vaut 0) :
 

#!/bin/bash
continuer=0
while test $continuer -eq 0
# ou -> while [$continuer -eq 0 ]
do
  echo "Appuyez sur 0 pour répéter ..."
  read quitter
  echo "vive le Bash !"
done
echo "bye !"
read

2) La boucke until

La boucle until s'utilise de la même façon que la boucle while et possède les mêmes syntaxes. Cependant elle prend en paramètre l'expression de condition inverse que celle que prendrait while.

Exemple :

#!/bin/bash
quitter=1
until [  $quitter -eq 0   ]
do
   echo "Appuyez sur 0 pour quitter ..."
   read quitter
   echo "vive le Bash !"
done
echo "bye !"
read

Ce code parvient au même résultat que celui du premier exemple donné pour la boucle while.

3) La boucle for :

J'en vient directement à l'intérêt de la boucle for par rapport à la boucle while
à l'aide d'un exemple : on veut par exemple répeter la phrase "vive Linux"
tant que la valeur d'une variable est comprise entre 0 et 10 (exclus).
  

#!/bin/sh
i=0
for i in `seq 0 10`
do
   echo "vive Linux !"
   read i
done
echo "bye !"
read

 Ceci aurait pu s'écrire de la manière classique :

#!/bin/sh
i=0

for (( i=0 ; i<$value ; i++ ))
do
     echo "vive Linux !"
done
echo "bye !"
read


VI - Les fonctions :

Les fonctions sont très simples à faire en Bash, elles permettent
de ne pas répéter plusieurs fois le même bloc. Il faut indiquer
clairement lorque vous déclarez une fonction.

 
Exemple :

#!/bin/sh
function hello # déclaration de la fonction
{
    echo "Salut $1 !"
    #le $1 sert à insérer le contenu d'une variable,
    celui de la variable qui suivra l'appel de la fonction
}
echo "Comment t'appelles tu ?"
read name
hello $name
read

L'exemple utile de la fonction pause :

#!/bin/sh
pause () # autre forme de déclaration de fonction
{
     echo "Appuyez sur une touche pour continuer ..."
     read
}
pause # appel de la fonction

VII - Ou apprendre le Bash gratuitement sur Internet :

Pour approfondire vos connaissance, il existe de nombreux endroits ou apprendre la programmation en Bash (et dans les shells script en générale) gratuitement sur le net, en voici une liste :


Article d'InfosLinux   Contrat Creative Commons