Par Pat Eyler
De nombreux tutoriels et introductions à bash parlent de l'utilisation des alias. Malheureusement, la plupart d'entre eux ne traitent pas les fonctions. C'est vraiment dommage car les fonctions offrent de mutiples avantages que n'ont pas les alias.
Les alias sont de simples substitutions de chaînes. Le shell prend le premier mot d'une commande et le compare à la liste courante des alias. Par ailleurs, si le dernier caractère d'un alias est un espace, il regarde aussi le mot suivant. Par exemple :
$ alias 1='echo '
$ alias 2='ceci est un alias'
$ 1 2
ceci est un alias
$
Les alias ne proposent pas le support d'instructions de branchements,
d'arguments sur la ligne de commande ou tous les autres trucs qui rendent la
ligne de commande si utile. Par ailleurs, les règles gérant l'expansion des
alias sont un peu délicates, suffisamment pour que la page de man de bash
bash(1)
recommande: placez toujours les définitions d'alias sur des
lignes isolées, et n'utilisez jamais la commande alias dans les commandes
composées.
Les fonctions sont en fait des scripts qui tournent dans le contexte courant du shell. (Ce court moment de jargon technique veut dire qu'en l'occurrence, un second shell n'est pas démarré pour faire tourner la fonction, celle-ci est executée par le shell courant.) Les fonctions sont des scripts dans le plein sens du terme et possèdent donc la flexibilité et la puissance de ces derniers.
Vous pouvez créer des fonctions de différentes manières. Vous pouvez tout
simplement la stocker dans un fichier et exécuter le contenu avec la commande
.
(sur la ligne de commande ou dans un script de démarrage). Vous pouvez
également entrer la fonction sur la ligne de commande. Une fonction n'est ainsi
disponible que dans la session dans laquelle elle a été définie par l'une des
deux méthodes ci-dessus (ou alors dans une session héritée d'un shell parent).
Pour créer une fonction sur la ligne de commande, il vous faut faire comme suit :
$ gla() {
> ls -la | grep $1
> }
C'est une fonction plutôt simple qui pourrait également être implantée sous la forme d'un alias. (Les raisons pour lesquelles il ne vaut mieux pas le faire via un alias seront exposées plus tard.) Écrite comme précédemment, elle affiche une version plus détaillée du contenu du répertoire courant et recherche toutes les occurences du premier argument. Vous pourriez la rendre plus intéressante en utilisant awk pour trouver les fichiers qui dépassent 1024 octets. Cela donnerait:
$ gla() {
> ls -la | grep $1 | awk ' { if ( $5 > 1024 ) print $0 } '
> }
Vous ne pourriez pas faire cela avec un alias car il ne suffit plus de
remplacer gla
par ls -la | grep
. Comme elle est écrite sous forme
de fonction, cela ne pose pas de problème d'utiliser $1
(pour se référer
au premier argument de gla) n'importe où dans le corps de vos commandes.
Pour un exemple un peu plus conséquent (d'accord, bien plus conséquent),
supposez que vous travaillez sur deux projets avec deux dépôts CVS
différents. Vous voudrez certainement écrire une fonction qui donne les bonnes
valeurs aux variables CVSROOT
et CVS_RSH
ou encore qui efface ces
valeurs si un argument indéterminé est donné en argument. Il serait également
intéressant que la commande cvs update
soit lancée si vous donnez
l'argument update
à votre fonction. Avec des alias, vous pouvez le faire
mais seulement en lançant de mutiples alias sur la ligne de commande. En
utilisant des fonctions, vous pouvez créer un fichier texte (appelé par exemple
setcvs.sh
) contenant ce qui suit :
setcvs() {
export done="no"
if [ "$1" = "unset" ]
# Nous voulons effacer toutes les variables
then
echo -n "Vidage des variables en relation avec CVS : "
export CVSROOT=""
export CVS_RSH=""
export done="yes"
echo "Terminé"
fi
if ( pwd | grep projects/reporting > /dev/null && \
[ "$done" != "yes" ] )
# si nous sommes dans l'espace reporting et que cela n'a pas déjà
# été fait
then
echo -n "Mise en place de cvs pour le projet reporting : "
export CVSROOT="issdata:/usr/local/cvs/"
export CVS_RSH="ssh"
export done="yes"
echo "Terminé"
fi
if ( pwd | grep projects/nightly > /dev/null && \
[ "$done" != "yes" ] )
# si nous sommes dans l'espace nightly et que cela n'a pas déjà
# été fait
then
echo -n "Mise en place de cvs pour le projet nightly : "
export CVSROOT="/home/cvs/"
export done="yes"
echo "Terminé"
fi
if [ "$1" = "update" ]
# Nous voulons mettre à jour l arborescence courante vis à vis du
# serveur cvs après avoir initialisé les bonnes variables
then
if [ -z "$CVSROOT" ]
# si $CVSROOT est de longueur nulle (elle a été vidée ou n'a
# jamais été initialisée), lancer une erreur et ne rien faire
then
echo "variables cvs non intialisées ..."
echo "vérifiez le répertoire dans lequel vous vous trouvez et réessayez."
elif [ -n "$CVSROOT" ]
# si $CVSROOT est définie, essayer de faire la MAJ
then
echo "MAJ de l'arborescence locale"
cvs -q update
echo "Terminé"
fi
fi
}
Vous pouvez alors enregistrer la fonction et l'utiliser de la manière suivante :
$ . ~/scripts/setcvs
$ cd
$ pwd
/home/a257455
$ setcvs unset
Vidage des variables en relation avec CVS : Terminé
$ echo $CVSROOT
$ echo $CVS_RSH
$ cd projects/reporting/htdocs/
$ setcvs
Mise en place de cvs pour le projet reporting : Terminé
$ echo $CVSROOT
issdata:/usr/local/cvs/
$ echo $CVS_RSH
ssh
$ cd ../../nightly/
$ setcvs
Mise en place de cvs pour le projet nightly : Terminé
$ setcvs update
Mise en place de cvs pour le projet nightly : Terminé
MAJ de l'arborescence locale
Terminé
$ cd
$ setcvs unset
Vidage des variables en relation avec CVS : Terminé
$ setcvs update
variables cvs non intialisées ...
vérifiez le répertoire dans lequel vous vous trouvez et réessayez
.
$
Les fonctions peuvent faire bien plus que les alias : la fonction ci-dessus
montre l'utilisation de branchements simples, du contrôle d'erreur et de
variables. Bien sûr, elle pourrait être améliorée mais elle montre quand même
quelques points importants. Un autre aspect est que les fonctions peuvent être
réutilisées dans des scripts alors que ce n'est pas le cas pour les alias. Par
exemple, compte tenu du fait que la fonction ci-dessus est stockée dans un
fichier appelé ~/scripts/setcvs
, vous pouvez écrire un script comme
celui-ci :
#!/bin/bash
# un script d'exemple
# d'abord, charger les fonctions
. ~/scripts/setcvs
# aller dans les répertoires de projet et les mettre à jour via CVS
cd ~/projects/reporting/htdocs
setcvs update
cd -
cd ~/projects/nightly
setcvs update
# retourner d'où l'on vient et vider les variables CVS
cd -
setcvs unset
Les alias sont de petites choses bien pratiques mais j'espère qu'après cette introduction, vous allez trouver les fonctions au moins aussi intéressantes (et peut-être même plus utiles). Cependant un défaut commun aux alias et aux fonctions tient dans le fait que vous ne devriez pas remplacer une commande standard par un alias ou une fonction. Il est trop facile de causer des dommages en essayant d'exécuter votre alias alors qu'il n'est pas défini. Imaginez la différence entre :
$ alias rm='rm -i'
$ cd ~/scratch
$ rm * # ici l'alias à rm vous protège et vous efface de manière
# interactive le contenu du répertoire courant
et:
$ su -
# cd /tmp
# rm * # ici l'alias à rm n'existe plus et vous effacez
# tout ce qu'il y a dans /tmp
Joyeux hacking !
pate
Copyright © 2000, Pat Eyler. Paru dans le numéro 53 de la Linux Gazette de Mai 2000.
Traduction française de Pierre Tane