edix_shell_script(7f) edix_shell_script(7f)

edix_shell_script - L'écriture des scripts shell

On découvre usuellement les commandes du shell avec la pratique du terminal sous unix (voir edix_shell(7f), edix_terminal(7f) et edix_unix(7f)). Mais les commandes du shell peuvent aussi être saisies dans un fichier (un "script shell") de façon a créer un programme. Dans le cadre d'edix, les scripts shell portent l'extension .sh, par exemple ${EDIX}/bin/mise_a_jour_edix.sh est un script utilisé pour récuppérer la dernière version du projet edix.

Nous indiquons ici quelques éléments de la pratique d'écriture des scripts shell.

Nous allons prendre un exemple très simple : un script qui aurait comme objectif d'afficher le nom du répertoire courant, puis d'afficher le contenu de ce répertoire. Si nous souhaitions réaliser ces deux actions dans un terminal il suffirait de saisir

etudiant:~ $ pwd
etudiant:~ $ ls

Nous allons créer un script nommé premier_script.sh qui réalise ces deux actions.

Nous allons créer le fichier premier_script.sh qui contiendra trois lignes. La première ligne définira le statut de ce fichier, c'est à dire indiquera qu'il s'agit d'un script shell. La seconde et la troisième ligne contiendront les deux commandes :

etudiant:~ $ vim premier_script.sh
vim:

#!/bin/sh
pwd
ls

Ensuite on rend le script exécutable avec la commande suivante :


etudiant:~ $ chmod +x premier_script.sh

Avant d'exécuter un script, vous êtes fortement invités à contrôler sérieusement son contenu. Par exemple, si votre script efface un fichier, alors le fichier sera effacé et il n'y aura pas de retour en arrière. Une façon de faire peut être d'excécuter d'abord chaque ligne, une par une (en réfléchissant), dans un terminal.

La validation doit aussi être considérée sur un autre plan : s'assurer que le script est bien compatible avec la norme posix (voir edix_shell_posix(7f)). Pour cela on lance la commande suivante (voir unix_shellcheck(7f)) :

etudiant:~ $ shellcheck -x -o all premier_script.sh

Une fois que le script est validé, vous pouvez l'exécuter avec

etudiant:~ $ ./premier_script.sh

Si on souhaite que le script prenne en entrée un certain nombre de chaines de caractères, par exemple si on souhaite créer un script nommé second_script.sh qui prend en entrée deux chaines de caractères, la chaine repertoire et la chaine fichier et qui execute la commande ls -l sur repertoire/fichier, alors on utilise les variables positionnelles 1 et 2 :

etudiant:~ $ vim second_script.sh
vim:

#!/bin/sh
ls -l ${1}/${2}

que l'on exécute avec

etudiant:~ $ ./second_script.sh repertoire fichier

Dans le script ${1} reçoit repertoire alors que ${2} reçoit fichier.

On cherche souvent à utiliser des scripts shell qui contiennent des opérations numériques (des calculs). Cette question est délicate : le shell est fondamentalement construit à partir du concept de chaîne de caractère et n'a donc rien dédié au calcul numérique.

Il y a un choix à faire :

  • essayer de réaliser les calculs numériques en shell malgré le fait que le shell soit plutôt mal adapté au calcul nuérique ;
  • ou créer un ou plusieurs exécutables en langage C et les appeler depuis le shell.
Le seul conseil que l'on puisse donner est de ne pas hésiter à faire appel au C quand les difficultés du shell rendent le script illisible.

Assez fondamentalement, les variables du shell sont des chaines de caractères. Pour les opérations de calcul, on utilise la calculatrice bc(1p).

Imaginons que nous disposons d'une variable $var1 dont le contenu s'interprète numériquement et que nous souhaitons ajouter 1 à cette variable. La commande suivante réalise cette incrémentation :


etudiant:~ $ var1="$( printf "%sn" "$var1 + 1" | bc -l )"

Toutes les opérations de calcul peuvent être conçues de la même façon, en exploitant les potentialités de bc.

RQ: Attention aux opérations avec les variable en second terme. Par exemple "1 - $var1" peut ne pas fonctionner si var1=-3 car cela revient à écrire "1 --3" que bc ne comprend pas. Il faut donc écrire "1 - ($var1)".

Avant d'utiliser bc dans un script, vous pouvez tester si les opérations que vous utilisez sont bien valides en lançant bc en mode interactif :

etudiant:~ $ bc -l

Une boucle for prend en entree une suite de chaines de caractères séparées par un espace. Pour chacune des chaines, le contenur de la chaine est placée dans la variable d'indexation (ici var qui reçoit donc successivement chaine1, chaine2, chaine3 et chaine4) et les lignes de shell placées entre do et done sont exécutée (ici il n'y a qu'une ligne qui imprime le contenu de var) :


suite="chaine1 chaine2 chaine3 chaine4"
for var in ${suite}
do
printf "%sn" "${var}"
done

Cette boucle produit


chaine1
chaine2
chaine3
chaine4

Si on veut une boucle numérique, on peut utiliser la fonction seq :


suite=$(seq 1 6)
for var in ${suite}
do
printf "%sn" "${var}"
done

produit


1
2
3
4
5
6

i=1
while [ "$i" -ne 6 ]
do

printf "%sn" "$i"
i=$((i + 1)) done

produit


1
2
3
4
5

bc(1p), edix_shell(7f), edix_shell_posix(7f), edix_terminal(7f), edix_unix(7f)

2026-05-17 UNIX