À l'heure des interfaces graphiques, il peut paraitre inutile d'apprendre à programmer avec un shell, tout comme avec les batch files du DOS, mais, par exemple, il y a beaucoup d'administrateurs qui préfèrent exécuter leurs tâches par ces scripts : efficacité et rapidité. C'est une raison pour laquelle Microsoft à développé de nouvelles fonctionnalités et commandes dans son interpréteur livré avec Windows .NET. Comme ils ont mentionné : « DOS n'est pas mort, il était seulement en état de veille. » De toutes façons, ici on parle du bash !
Pourquoi ne pas utiliser ce qui est déjà là ? Bash est l'interpréteur de commandes installé par défaut par la majorité des distributions Linux, alors pourquoi charger un interprteur différent qui prendra de la mémoire de plus inutilement ? Là, prêt à utiliser en tout temps.
De plus, la puissance de l'interpréteur se révèle assez rapidement lorsqu'on l'utilise. Beaucoup plus avancé que le langage du MS-DOS par exemple, les possibilités sont virtuellement illimités. Il est même possible de graver un disque à l'aide d'un script bash.
Il faut noter que sous les systèmes d'exploitation Unix-like, il n'y a pas nécessairement d'extentions de fichiers. Par exemple, dans les scripts Windows, les fichiers doivent se terminer soit par .cmd
ou par .bat
. Ici, il faudra changer les attributs du fichier avec chmod
pour le rendre exécutable. Vous pouvez ajouter des extentions aux fichiers, mais ce sera de façon personnelle, car le système d'exploitation ne le prendra pas en compte. Un script Perl peut terminer par .pl
ou .cgi
par exemple.
Aussi, sous Linux le répertoire courant ne fait pas parti du chemin de recherche. Pour exécuter un script, il faudra préciser le répertoire courant :
$ ./script
Ou bien modifier le chemin de recherche :
$ set PATH=$PATH:<nouveau_chemin> $ set PATH=$PATH:/home/johndoe
Pour créer un premier script, il faut généralement un éditeur de texte. vi
offert avec la plupart des systèmes d'exploitation Unix-like, peut très bien faire l'affaire.
$ vi scriptbash
À la première ligne du script, il faut indiquer sur quel shell il doit être interprété :
#!/bin/bash
Commençons par le plus simple. Pour bien autodocumenter le script, il est fortement suggéré d'appliquer les commentaires aux bons endroits, surtout si le script fait plusieurs pages. Il n'y a qu'une seule façon de produire des commentaires et c'est en utilisant le caractère dièse (ou carré) : #
. Dès que ce caractère est placé sur une ligne quelconque, tout est ignoré à la suite de celui-ci.
#=========================================================# # VARIABLES # #=========================================================# choix=1 # option entrée par l'utilisateur proc_actif=0 # détermine s'il y a des processus actifs
La commande read
permet de faire la saisie d'un utilisateur et la placer dans une variable.
read [-t timeout] [-p prompt] variable
read choix read -p "Entrez un choix : " choix
Il faut utiliser le if
pour tester les variables.
if expr then instruction elif expr then instruction2 else instruction3 fi
La ligne du if
peut s'écrire if expr; then
en n'oubliant pas le point-virgule. Même principe avec la ligne du elif : elif expr; then
.
Voici le tableau des différentes switches pour faire les tests de nombres dans le format if [$nbparam -eq 1]
(à titre d'exemple) :
switch | équivalent | Signification |
---|---|---|
-eq | = | égal |
-ne | <> | Différent |
-lt | < | Inférieur |
-le | <= | Inférieur ou égal |
-gt | > | Plus grand |
-ge | >= | Plus grand ou égal |
Le tableau pour comparer les chaînes if [$chaine1 == $chaine2]
:
Test | Signification |
---|---|
-n | Est une chaîne (non nulle) |
== | Égales |
!= | Différentes |
< | Vrai si chaîne1 se trouve avant chaine2 |
> | Vrai si chaîne1 se trouve après chaine2 |
Et finalement, pour gérer les fichiers :
switch | Signification |
---|---|
-f | Le fichier existe |
-d | Le répertoire existe |
-s | Fichier a des données |
La commande case
permet de faire plusieurs tests de valeurs sur le contenu d'une même variable. Notez le esac
qui termine le case
.
read reponse case $reponse in [oO]) echo "Vous avez dit oui" echo "Appuyez sur [N]";; [nN]) echo "Vous avez dit non" echo "Choix erroné";; esac
Pour créer des fonctions, c'est simple, suffi de les déclarer avant leur appel, donc, préférablement au début du script.
#!/bin/bash function nom_de_la_fonction () { instruction1 instruction2 instructionn } instructions nom_de_la_fonction # appel de la fonction instructions exit
Ce sont les paramètres entrés lors du lancement du script :
$ lescript param1 param2 param3 paramn [...]
La variable $#
contient le nombre de paramètres entrés. Pour avoir accès aux paramètres, utiliser les variables $0
(script lui-même), $1
, $2
, $3
, $4
, etc.
Pour terminer le script et en sortir, il faut placer un exit
. Ce sera soit à la fin du script, soit là où il est nécessaire.
LOGFILE=/tmp/log command | tee -a $LOGFILE
echo $'\r' >> $LOGFILE
L'exemple suivant peut être utile pour voir un peu la structure d'un script écrit en bash. L'objectif du script, c'est de permettre l'effacement d'un fichier, en le plaçant dans un répertoire créé /corb.dir
. Ce dernier, comme son nom l'indique, sert de corbeille.
#!/bin/bash ####################################################### # Script : sdel ver.: 0.5.0.1 # # Auteur : Stephane Gariépy # # Date : 19 décembre 2005 # # But : Efface (ou déplace) un fichier dans un # # répertoire Corbeille (~/corb.bin) spécifié # # en paramètre. # ####################################################### function afficher_aide_fr { echo " " echo "SYNTAXE : sdel [SPECFICH][-h]" echo "SPECFICH : Représente une spécification de fichier selon la syntaxe" echo " suivante : [chemin]/[nomfich]" echo "Exemple 1 : sdel -h (affiche cet écran d'aide)" echo "Exemple 2 : sdel toto (Déplace le fichier toto dans ~/corb.dir)" echo " " read -p "Appuyez sur une touche pour quitter..." } function afficher_aide_en { echo " " echo "SYNTAX : sdel [SPECFICH][-h]" echo "SPECFICH : Represents a file specification using the following syntax :" echo " [path]/[filename]" echo "Example 1 : sdel -h (Shows this help screen)" echo "Example 2 : sdel toto (Moves toto to the recycle bin ~/corb.dir)" echo " " read -p "Hit any key to quit..." } function validation_langue { case $rep_langue in [fF]) afficher_aide_fr;; [eE]) afficher_aide_en;; *) choix_langue;; esac return } function choix_langue { clear read -p "Quelle langue préférez-vous ? / Which language do you prefer ? (F)rançais ou/or (E)nglish ?" rep_langue validation_langue return } function deplacer_fichier { mv $specfich ~/corb.dir return } function demander_ecraser_fichier { read -t 10 -p "Le fichier $fichier existe dans ~/corb.dir. Voulez-vous écraser ?" rep_ecraser case $rep_ecraser in [oOyY]) deplacer_fichier;; [nN]) exit;; *) exit;; esac return } function creer_corbeille { mkdir ~/corb.dir return } specfich=$1 fichier=${1##*/} corbeille="~/corb.dir" corb_fich="~/corb.dir/$fichier" if [ $# -eq 1 ] #vérification du nb de param then if [ $1 == "-h" ] #vérification du param -h then choix_langue else if [ -f $1 ] #fichier $1 existe ? then if [ -d ~/corb.dir ] then if [ -f ~/corb.dir/$fichier ] then demander_ecraser_fichier else deplacer_fichier fi else #corb.dir n'existe pas creer_corbeille deplacer_fichier fi else echo "Fichier $1 introuvable." fi fi else choix_langue fi
# Renommer des fichiers avec espaces
$ for f in *\ *; do mv "$f" "${f// /_}"; done