include

Script

Ce billet explique comment inclure un script Bash dans un autre script Bash. Cette possibilité est très utile pour éviter de dupliquer du code réutilisable ou pour créer des fonctions pouvant être appelées dans tous vos scripts.

Quand on écrit plusieurs scripts Unix, il arrive souvent que l'on souhaite réutiliser du code qui provient d'un autre script. La solution la plus simple est de recopier le code en question. Le souci c'est que si l'on souhaite changer le code à postériori, il faut le faire dans tous les scripts qui l'utilisent. Et plus compliqué, il faut savoir dans quels scripts le code a été dupliqué.

Une solution qui évite ces deux inconvénients est de placer le code à reprendre dans un fichier de script séparé et d'inclure ce fichier dans les scripts qui doivent l'exécuter.

Comment inclure un fichier de script.

Créez un premier script include.sh avec la commande...

nano include.sh

Dans lequel vous allez rédiger le code ...

echo "Ce message provient du fichier de script 'include.sh'."

Créez un deuxième script main.sh avec la commande ...

nano main.sh

Dans lequel vous allez appeler le fichier à un inclure pour que son code le script qu’il contient soit exécuté tout en rajoutant ensuite in script supplémentaire comme ceci…

#!/bin/bash
source include.sh
echo "Ce message provient du fichier de script 'main.sh'."

Remarque : Seul le fichier principal doit contenir la déclaration de l'interpréteur de script #!/bin/bash qui sera utilisé pour exécuter le code du script.

Ce script principal utilise la commande source qui indique que l'on souhaite exécuter le code contenu dans le fichier include.sh. Puis il affiche un message.

Attention : Pour qu'un fichier de script puissent être lancé en ligne de commande, il faut le rendre exécutable avec la commande chmod +x suivi du nom du fichier à autoriser.

En exécutant ce script principal avec la commande...

./main.sh

Vous aurez le résultat suivant

Ce message provient du fichier de script 'include.sh'.
Ce message provient du fichier de script 'main.sh'.

Autre méthode d'inclusion du fichier.

Il est possible de remplacer la commande d'inclusion...

source include.sh

par...

. "include.sh"

Exécution du script à partir d'un autre emplacement.

Dans l'exemple précédent, les deux fichiers sont placés dans un même dossier, par exemple scripts. On n'a pas précisé dans le script 'main.sh' l'emplacement exact du fichier inclus. Lors de l'exécution de la commande, le système ne va pas rechercher le fichier include.sh au même endroit que le fichier main.sh mais à l'endroit d'où l'on exécute la commande.

Si on lance le script main.sh à partir de l'emplacement où il se trouve, le script s'exécutera correctement. Mais si on l'exécute à partir d'un autre emplacement, par exemple le dossier parent avec la commande ...

./scripts/main.sh

… le résultat sera le suivant ...

./scripts/main.sh: line 2: include.sh: No such file or directory
Ce message provient du fichier de script 'main.sh'.

Le système n'a pas retrouvé le fichier inclus car il l'a recherché à l'endroit d'où l'on a exécuté la commande. C'est à dire le dossier parent de scripts et non le dossier scripts lui-même.

Une première méthode pour résoudre ce problème consiste à indiquer l'emplacement exact du fichier ...

source $HOME/scripts/include.sh

Dans cet exemple, la variable $HOME permet de retrouver l'emplacement du dossier de l'utilisateur qui contient à sa racine le dossier scripts.

Mais si l'on a placé les deux fichiers dans un autre dossier, en les ayant, par exemple, téléchargés, l'emplacement exact du fichier include.sh tel qu'il est défini dans le fichier main.sh ne fonctionnera plus. Pour que cela fonctionne systématiquement il faut déterminer l'emplacement exact du fichier include.sh par rapport à l'emplacement du fichier main.sh et ce quel que soit l'emplacement d'où l'on exécute le script. Cela ne fonctionnera bien sûr qu'à condition que l'emplacement relatif du fichier include.sh soit toujours le même par rapport au fichier main.sh.

On retrouve l'emplacement exact d'un fichier inclus par rapport à l'emplacement du fichier principal en utilisant la méthode suivante dans le script du fichier principal...

DIR="${BASH_SOURCE%/*}"
if [[ ! -d "$DIR" ]]; then DIR="$PWD"; fi
. "$DIR/include.sh"
echo "Ce message provient du fichier de script 'main.sh'."

Dans ce script la variable BASH_SOURCE est une variable système qui contient le chemin du script qui y fait appel. Le complément de commande %/* permet de retrouver dans la variable le dernier caractère / et le supprime ainsi que tous les caractères qui le suivent. Donc si l'on exécute le script avec la commande...

./scripts/main.sh

La commande ${BASH_SOURCE%/*}renverra la valeur ./scripts et non la valeur de la variable BASH_SOURCE qui est ./script/main.sh car la commande aura supprimé le dernier / et tous les caractères qui le suivent. C'est à dire /main.sh.

Un test est ensuite réalisé pour s'assurer que la valeur retournée est bien un emplacement. Si ce n'est pas le cas alors le script récupère l'emplacement d'où l'on exécute ce même script en récupérant la valeur de la variable système PWD.

Et voilà, vous disposez maintenant de toutes les bases pour éviter de dupliquer le code de vos scripts.

Previous Post Next Post