Programmation de scripts en shell

Un shell, quel qu'il soit, peut exécuter des commandes prises dans un fichier. Un fichier contenant des commandes pour le shell est appelé un script. C'est en fait un programme écrit dans le langage du shell. Ce langage comprend non seulement les commandes que nous avons déjà vues, mais aussi des structures de contrôle (constructions conditionnelles et boucles).

Pour la programmation du shell, nous allons utiliser le shell sh, qui est le plus répandu et standard. Ce que nous avons vu jusqu'ici s'applique aussi bien à sh qu'à zsh et aussi à csh, à l'exception de setenv et de certaines redirections signalées.

Créer un script

Rendre un script exécutable

Pour être un script, un fichier doit commencer par la ligne:

#!/bin/sh

Il doit aussi avoir être exécutable (bit x). Le #!/bin/sh sur la première ligne indique que ce script doit être exécuté par le shell sh dont on indique le chemin d'accès. Pour rendre un fichier exécutable, tapez :

chaland ~ chmod u+x fichier

(pour en savoir plus sur les droits attachés à un fichier, consultez la page sur les droits d'accès).

Le chemin d'une commande

Pour comprendre ce qui suit, vous devez savoir ce qu'est le PATH. Si ce n'est pas le cas, lisez la page principale sur le shell.

Quand vous exécutez un script, vous pouvez vous trouver à n'importe quel endroit de l'arborescence de vos répertoires. Si le répertoire courant ne se situe pas dans votre PATH et que vous voulez exécuter un programme qui s'y trouve, vous ne pouvez pas taper :

clipper ~ commande

car si le répertoire courant n'est pas dans le PATH, le shell n'ira pas y chercher commande.

Vous recevrez donc un message comme :

clipper ~ commande
zsh: command not found: commande

Spécifier le chemin d'une commande

Pour que le shell comprenne où chercher votre commande, il faut donc spécifier l'emplacement de la commande en donnant son chemin, qu'il soit absolu :

clipper ~ /home/toto/repertoire/courant/commande

ou relatif :

clipper ~ repertoire/courant/commande

ou encore sous la forme :

clipper ~/repertoire/courant ./commande

Le répertoire ~/bin

Il y a un certain nombre de commandes que l'on peut vouloir utiliser depuis n'importe quel répertoire. Dans ce cas, il est fastidieux de :

Il suffit donc de mettre tous vos scripts dans un même répertoire, et de mettre ce répertoire dans le PATH. Par convention, ce répertoire s'appelle bin et se place dans votre répertoire personnel. Si votre répertoire personnel est /home/toto, ce répertoire sera donc /home/toto/bin.

Commencez donc par créer ce répertoire :

clipper ~ mkdir bin

Ensuite, vérifiez qu'il soit bien dans votre PATH :

clipper ~ echo $PATH

Si vous voyez par exemple $HOME/bin dans votre PATH, alors c'est bon, tous les fichiers exécutables situés dans ce répertoire seront accessibles depuis n'importe quel répertoire.

Si ce n'est pas le cas, il faut ajouter ce répertoire au PATH. Pour cela, ajoutez dans le fichier de configuration de votre shell, par exemple le fichier .zshrc, la ligne :

PATH=$PATH:$HOME/bin

Cette ligne indique que la prochaine fois que vous ouvrirez votre shell, le répertoire bin figurera dans votre PATH.

Principes généraux des scripts shell

Une succession de commandes

Si vous manipulez déjà le shell en ligne de commande, vous pouvez commencer vos premiers scripts. Un script shell est en effet avant tout une succession de commandes.

Par exemple, si vous avez coutume de taper successivement, quand vous vous loguez à l'ENS :

clipper ~ mozilla &
clipper ~ mutt

vous pouvez vous créer le script suivant dans le fichier ~/bin/amorce :

#!/bin/sh

mozilla &
mutt

Ainsi, dès que vous vous connectez, vous pouvez taper amorce dans le shell, et vos commandes s'exécuteront automatiquement.

Commentaires

Presque tous les langages informatiques autorisent d'insérer des commentaires ; le shell n'échappe pas à la règle. Pour cela, il suffit de faire précéder chaque ligne de commentaire du caractère « # ». Exemple :

#!/bin/sh

# Tout ce que j'écris ici ne sera pas lu.
echo "Ce que je tape ici sera lu."

Les lignes blanches ne sont pas interprétées non plus. N'hésitez donc surtout pas à espacer votre script, les lignes blanches ne consomment presque rien en termes d'espace disque, ce n'est donc pas une ressource rare.

L'impératif de lisibilité

Pourquoi espacer son script ? Pourquoi insérer des commentaires ? Pour une seule et même raison : votre script doit être lisible. Pourquoi être lisible ?

D'abord, pour autrui : si d'autres gens lisent votre script, il doit être intelligible, et les passages complexes doivent être explicités par des commentaires.

Ensuite, pour vous-même ; au moment où vous écrivez un script, vous comprenez tout, naturellement ; mais si vous le relisez dans quelques mois, voire quelques années, les passages obscurs risqueront d'être incompréhensibles, ce qui est particulièrement pénible quand on essaye de débuguer un programme, c'est-à-dire d'en corriger les erreurs.

Un script qui parle : la commande echo

Maintenant que vous savez comment on peut exécuter un script, il s'agit de le remplir... Commençons par ce qu'il y a de plus simple : afficher du texte.

Hello World !

Traditionnellement, on commence par faire un programme qui affiche simplement la ligne « Hello world » (ce qui signifie en anglais : bonjour au monde entier). Faites donc un fichier helloworld contenant les lignes suivantes :

#!/bin/sh

# Fichier "helloworld"
echo "Hello world"

Exécutez ensuite ce programme, par exemple en tapant, dans le répertoire où il se trouve :

clipper ~ $ ./helloworld
Hello world

Ça y est, vous avez créé votre premier programme ! Lancez-le autant de vous que vous voulez, vous avez bien mérité d'être fier de vous.

Exercice : francisez ce script.

La commande echo

La commande echo sert à afficher du texte sur la sortie standard (pour savoir ce qu'est la sortie standard, consultez la page sur les entrées et sorties). Chaque ligne de texte est écrite sur une ligne à part. Exemple :

#!/bin/sh
# Fichier "bonjour"

echo "Bonjour... "
echo "Comment allez-vous ?"

affiche les lignes suivantes :

Bonjour... 
Comment allez-vous ?

et non :

Bonjour... Comment allez-vous ?

Annuler le retour chariot

Si vous voulez annuler le retour chariot qui a lieu par défaut à la fin de toute commande echo, il faut utiliser l'option -n. Le programme sera alors :

#!/bin/sh

echo -n "Bonjour..."
echo "Comment allez-vous ?"

Alors seulement, vous pourrez avoir :

Bonjour... Comment allez-vous ?

Citer des variables

Faisons mieux encore : votre script va citer des variables. Pour savoir ce que sont des variables, allez voir la page sur les variables.

La variable USER contient le login de l'utilisateur ; la variable PWD (pour print working directory) affiche le répertoire courant. Faisons donc le script suivant :

#/bin/sh
# Fichier "mon-pwd"

echo "Bonjour $USER..."
echo "Tu es actuellement dans le répertoire $PWD."

Comme vous pouvez le remarquer, pour citer le contenu d'une variable, on ajoute le signe dollar ($) devant son nom.

Un script qui écoute : la commande read

Parler c'est bien, écouter c'est mieux. Jusqu'ici, votre programme est capable de parler, de dire bonjour, mais il n'est même pas capable de vous appeler par votre nom, tout juste par votre login, ce qui n'est pas très intime...

Nous allons donc lui donner la faculté d'écouter, grâce à la commande read. Prenons le script suivant :

#!/bin/sh
# Fichier "mon-nom"

echo "Bonjour... Comment vous-appelez-vous ?"
read nom
echo "Je vous souhaite, $nom, de passer une bonne journée."

Vous connaissez déjà la commande echo. La commande read permet de lire des variables. Si vous exécutez ce script, après avoir affiché la ligne

Bonjour... Comment vous-appelez-vous ?

le shell va attendre que vous tapiez votre nom. Tapez par exemple Toto, puis appuyez sur Entrée, et vous verrez :

Bonjour... Comment vous-appelez-vous ?
Toto
Je vous souhaite, Toto, de passer une bonne journée.
La commande read doit être suivie du seul nom de la variable, non précédé du signe dollar. Le signe dollar ne doit précéder le nom de la variable que lorsque l'on cite son contenu.

Lire plusieurs variables

La commande read permet également de lire plusieurs variables. Il suffit pour cela d'indiquer à la suite les noms des différentes variables. Exemple :

#!/bin/sh
# Fichier "administration"

echo "Écrivez votre nom puis votre prénom :"
read nom prenom
echo "Nom : $nom"
echo "Prénom : $prenom"

Vous aurez :

Écrivez votre nom puis votre prénom :
Hugo Victor
Nom : Hugo
Prénom : Victor

Appuyer sur Entrée pour continuer

Nous avons vu comment utiliser read avec un seul argument et avec plusieurs arguments ; il reste à voir l'usage de read sans argument. Oui, c'est possible ! Cela équivaut simplement à attendre un réaction de l'utilisateur, mais sans mémoriser ce qu'il tape.

Concrètement, cela est très utile après un message « Appuyez sur Entrée pour continuer. » Exemple :

#!/bin/sh
# Fichier "continuer"

echo "Quelle est la différence entre un canard ?"
echo "(Appuyez sur Entrée pour avoir la réponse)"
read
echo "Les pattes, surtout la gauche."
Auteur : Baptiste Mélès. Dernière modification le .