Chapitre 3. L'environnement du Bash

Table des matières

1. Les fichiers d'initialisation du Shell
1.1. Les fichiers de configuration qui agissent sur tout le système
1.2. Les fichiers de configuration utilisateur
1.3. Modification des fichiers de configuration du Shell
2. Variables
2.1. Types de variables
2.2. Créer des variables
2.3. Exporter les variables
2.4. Variables réservées
2.5. Paramètres Spéciaux
2.6. Script à finalités multiples grâce aux variables
3. Echappement et protection de caractères
3.1. Pourquoi protéger ou 'échapper' un caractère?
3.2. Le caractère Echap (escape)
3.3. Les apostrophes
3.4. Les guillemets
3.5. Codage ANSI-C
3.6. Particularités
4. Le processus d'expansion de Shell
4.1. Généralité
4.2. L'expansion d'accolades
4.3. L'expansion du tilde
4.4. Paramètre Shell et expansion de variable
4.5. La substitution de commande
4.6. L'expansion arithmétique
4.7. La substitution de processus
4.8. Le découpage de mots
4.9. Expansion de noms de fichier
5. Alias
5.1. Que sont les alias?
5.2. Créer et supprimer des alias
6. Plus d'options Bash
6.1. Afficher les options
6.2. Changer les options
7. Résumé
8. Exercices

Résumé

Dans ce chapitre nous traiterons des diverses façons de modifier l'environnement du Bash:

  • En modifiant les fichiers d'initialisation du Shell

  • En utilisant des variables

  • En utilisant divers modes d'échappement

  • En effectuant des calculs arithmétiques

  • En déclarant des alias

  • En employant l'expansion et la substitution

1. Les fichiers d'initialisation du Shell

1.1. Les fichiers de configuration qui agissent sur tout le système

1.1.1. /etc/profile

Si il est invoqué interactivement avec l'option --login ou si il est invoqué en tant que sh, Bash lit les instructions de /etc/profile. Ce qui généralement définit les variables PATH, USER, MAIL, HOSTNAME et HISTSIZE.

Sur certains systèmes la valeur umask est définie dans /etc/profile; sur d'autres ce fichier indique d'autres fichiers de configuration tel que:

  • /etc/inputrc, le fichier d'initialisation Readline agissant sur tout le système où vous pouvez définir le type de sonnerie de la ligne de commande.

  • le répertoire /etc/profile.d qui contient les fichiers de configuration propres à certains programmes.

Tous les paramétrages de l'environnement des utilisateurs devraient être dans ce fichier. Il pourrait ressembler à ça:

# /etc/profile

# Environnement général du système et programmes de démarrage pour le paramétrage du login

PATH=$PATH:/usr/X11R6/bin

# No core files by default
ulimit -S -c 0 > /dev/null 2>&1

USER="`id -un`"
LOGNAME=$USER
MAIL="/var/spool/mail/$USER"

HOSTNAME=`/bin/hostname`
HISTSIZE=1000

# Clavier, sonnerie, style d'affichage: le fichier de configuration readline:
if [ -z "$INPUTRC" -a ! -f "$HOME/.inputrc" ]; then
    INPUTRC=/etc/inputrc
fi

PS1="\u@\h \W"

export PATH USER LOGNAME MAIL HOSTNAME HISTSIZE INPUTRC PS1

# Source des fichiers d'init de programmes spécifiques (ls, vim, less, ...)
for i in /etc/profile.d/*.sh ; do
    if [ -r "$i" ]; then
        . $i
    fi
done

# Paramètrage de programmes d'initialisation
source /etc/java.conf
export NPX_PLUGIN_PATH="$JRE_HOME/plugin/ns4plugin/:/usr/lib/netscape/plugins"

PAGER="/usr/bin/less"

unset i

Ce fichier de configuration définit quelques variables de base de l'environnement du Shell ainsi que quelques variables requises par les utilisateurs lançant Java et/ou des applications Java depuis leur navigateur. Voir Section 2, « Variables ».

Voir Chapitre 7, Les instructions de condition pour en savoir plus sur les structures if employées dans ce fichier; Chapitre 9, Tâches répétitives traite des boucles tel que for.

Le source Bash contient des exemples de fichiers profile pour un usage courant ou particulier. Ceux-ci et celui donné en exemple ci-dessus nécessitent des adaptations propres à les faire fonctionner dans votre environnement.

1.1.2. /etc/bashrc

Sur des systèmes qui disposent de divers Shell, il peut être plus judicieux de configurer des particularités de Bash dans ce fichier, sachant que /etc/profile est aussi lu par d'autres Shells, comme Bourne Shell. Pour éviter que se produisent des erreurs de syntaxe par des Shells qui ne comprennent pas la syntaxe de Bash le fichier de configuration de chaque Shell est différent. Ce qui implique que le fichier utilisateur ~/.bashrc devrait indiquer /etc/bashrc de sorte à l'inclure dans l'initialisation du Shell lors de la phase de login.

Vous pouvez aussi trouver sur votre système un /etc/profile qui ne mémorise que le paramétrage de l'environnement Shell et du programme de démarrage, tandis que /etc/bashrc mémorise les définitions à portée globale (tout le système Shell) des fonctions et alias. Le fichier /etc/bashrc peut être référencé dans /etc/profile ou dans chacun des fichiers d'initialisation du Shell utilisateur.

Le source contient des exemples de fichiers bashrc, ou vous pouvez en trouver une copie dans /usr/share/doc/bash-2.05b/startup-files. Ceci fait partie de bashrc et accompagne la documentation Bash:

alias ll='ls -l'
alias dir='ls -ba'
alias c='clear'
alias ls='ls --color'

alias mroe='more'
alias pdw='pwd'
alias sl='ls --color'

pskill()
{
        local pid

        pid=$(ps -ax | grep $1 | grep -v grep | gawk '{ print $1 }')
        echo -n "killing $1 (process $pid)..."
        kill -9 $pid
        echo "slaughtered."
}

A part les alias généraux, il contient des alias pratiques qui rendent correctes des commandes même mal libéllées. Nous traiterons des alias à la Section 5.2, « Créer et supprimer des alias ». Ce fichier contient une fonction pskill; qui sera étudiée en détail au Chapitre 11, Fonctions.

1.2. Les fichiers de configuration utilisateur

Je n'ai pas ces fichiers?!

Ces fichiers peuvent être absent de votre répertoire racine; créez-les au besoin.

1.2.1. ~/.bash_profile

C'est le fichier de configuration principal pour définir l'environnement personnel. Dans ce fichier l'utilisateur peut ajouter des options de configuration supplémentaires ou changer le paramétrage par défaut:

franky~> cat .bash_profile
#################################################################
#                                                               #
#   .bash_profile file                                          #
#                                                               #
#   Exécuter depuis le Shell Bash quand vous vous loggez.               #
#                                                               #
#################################################################

source ~/.bashrc
source ~/.bash_login
case "$OS" in
  IRIX)
    stty sane dec
    stty erase
    ;;
#  SunOS)
#    stty erase
#    ;;
  *)
    stty sane
    ;;
esac

Cet utilisateur configure le caractère retour arrière selon le système d'exploitation sur lequel il se connecte. A part ça, .bashrc et .bash_login sont lus.

1.2.2. ~/.bash_login

Ce fichier contient des ordres de paramétrage spécifiques qui sont normalement exécutés seulement quand vous vous connectez au système. Dans l'exemple nous l'utilisons pour définir la valeur de umask et pour afficher une liste des utilisateurs connectés. Cet utilisateur obtient aussi le calendrier du mois:

#######################################################################
#                                                                     #
#   Bash_login file                                                   #
#                                                                     #
#   instructions à exécuter par le Shell Bash à l'étape de connection             #
#   (sourced from .bash_profile)                                      #
#                                                                     #
#######################################################################
#   paramétrer les permissions par défaut
umask 002       # Toutes pour moi, lecture pour le groupe et les autres
#   diverses actions
w
cal `date +"%m"` `date +"%Y"`

En l'absence de ~/.bash_profile, ce fichier sera lu.

1.2.3. ~/.profile

En l'absence de ~/.bash_profile et ~/.bash_login, ~/.profile est lu. Il peut définir le même paramétrage, qui alors peut être accessible aux autres Shells. Rappelez-vous que les autres Shells peuvent mal interpréter la syntaxe Bash.

1.2.4. ~/.bashrc

Aujourd'hui il est plus courant d'utiliser un Shell hors connection, par exemple quand vous vous connectez via une interface graphique de type X terminal. A l'ouverture de la fenêtre, l'utilisateur n'a pas besoin de fournir un nom et un mot de passe: pas d'authentification. Bash cherche ~/.bashrc dans ce cas, et de même à la connection ce fichier est référencé dans le fichier de configuration de connection, ce qui évite d'entrer le même paramétrage dans différents fichiers.

Dans ce fichier utilisateur, .bashrc, un ensemble de variables pour des programmes spécifiques et d'alias est défini après que le fichier à usage global /etc/bashrc ait été lu:

franky ~> cat .bashrc
# /home/franky/.bashrc

# Source de définitions globales
if [ -f /etc/bashrc ]; then
       . /etc/bashrc

fi

# shell options

set -o noclobber

# mes variables Shell

export PS1="\[\033[1;44m\]\u \w\[\033[0m\] "
export PATH="$PATH:~/bin:~/scripts"

# mes alias

alias cdrecord='cdrecord -dev 0,0,0 -speed=8'
alias ss='ssh octarine'
alias ll='ls -la'

# paramétrage de mozilla

MOZILLA_FIVE_HOME=/usr/lib/mozilla
LD_LIBRARY_PATH=/usr/lib/mozilla:/usr/lib/mozilla/plugins
MOZ_DIST_BIN=/usr/lib/mozilla
MOZ_PROGRAM=/usr/lib/mozilla/mozilla-bin
export MOZILLA_FIVE_HOME LD_LIBRARY_PATH MOZ_DIST_BIN MOZ_PROGRAM

# paramétrage des fontes
alias xt='xterm -bg black -fg white &'

# paramétrage de BitchX
export IRCNAME="frnk"

# La fin
franky ~>

Plus d'exemples se trouvent dans le paquetage Bash. Rappelez-vous que les fichiers exemples peuvent nécessiter des adaptations afin de les faire fonctionner dans votre environnement.

Les alias sont traités à la Section 5, « Alias ».

1.2.5. ~/.bash_logout

Ce fichier contient des instructions spécifiques pour la phase de déconnexion(logout). Dans cet exemple, la fenêtre du terminal est effacée à la déconnexion. C'est utile pour les connections à distance qui de cette façon laisse une fenêtre vide après la déconnexion.

franky ~> cat .bash_logout
#######################################################################
#                                                                     #
#   Bash_logout file                                                  #
#                                                                     #
#  instructions exécutées par le Shell Bash à la déconnexion            #
#                                                                     #
#######################################################################
clear
franky ~>

1.3. Modification des fichiers de configuration du Shell

Quand vous modifiez n'importe lequel des fichiers ci-dessus, les utilisateurs doivent soit se reconnecter, soit exécuter (source) le fichier modifié afin que prennent effet les modifications. De la deuxième manière, les modifications sont appliquées à la session active du Shell:

Figure 3.1. Différentes invites pour des utilisateurs différents

L'invite 1 est "franky ~>" l'invite est alors changée par "export PS1="\[\033[1;42m\]$USER is in \w\[\033[0m\] " ce qui a pour effet d'afficher le nom d'utilisateur et le répertoire courant sous une forme lisible en inverse vidéo vert. L'invite de 'root' est défini de la même manière par définition de PS1 en inverse vidéo rouge brillant.

La plupart des scripts Shell s'exécutent dans leur propre environnement: les processus enfants n'héritent pas des variables du parent à moins que celui-ci les exportent. Exécuter avec <c0>source</c0> un fichier contenant des instructions Shell est un moyen d'appliquer les changements à son propre environnement, de définir des variables dans son Shell actif.

Cet exemple montre aussi le paramétrage de diverses invites pour divers utilisateurs. Dans ce cas, rouge signifie danger. Si vous avez une invite verte, ne vous inquiétez pas trop.

Notez que source resourcefile est équivalent à . resourcefile.

Si vous vous trouvez perdu avec tous ces fichiers de configuration, et que vous ne ciblez pas où un certain paramètre est défini, employez echo, tout comme pour debugger un script; voir la Section 3.2, « Débugger qu'une partie du script ». Vous pouvez ajouter des lignes comme celles-ci:

echo "Avant exécution de .bash_profile.."

ou comme celles-ci:

echo "Avant définition de PS1 dans .bashrc:"
export PS1="[la bonne valeur]"
echo "PS1 est défini comme ceci $PS1"

2. Variables

2.1. Types de variables

Comme dans l'exemple ci-dessus, les variables Shell sont en majuscule par convention. Bash garde une liste de 2 types de variables:

2.1.1. Les variables Globales

Les variables Globales ou variables d'environnement sont disponibles dans tous les Shells. Les commandes env ou printenv peuvent être employées pour afficher les variables d'environnement. Ces programmes font partis du paquetage sh-utils.

Ci-dessous un affichage fréquent:

franky ~> printenv
CC=gcc
CDPATH=.:~:/usr/local:/usr:/
CFLAGS=-O2 -fomit-frame-pointer
COLORTERM=gnome-terminal
CXXFLAGS=-O2 -fomit-frame-pointer
DISPLAY=:0
DOMAIN=hq.xalasys.com
e=
TOR=vi
FCEDIT=vi
FIGNORE=.o:~
G_BROKEN_FILENAMES=1
GDK_USE_XFT=1
GDMSESSION=Default
GNOME_DESKTOP_SESSION_ID=Default
GTK_RC_FILES=/etc/gtk/gtkrc:/nethome/franky/.gtkrc-1.2-gnome2
GWMCOLOR=darkgreen
GWMTERM=xterm
HISTFILESIZE=5000
history_control=ignoredups
HISTSIZE=2000
HOME=/nethome/franky
HOSTNAME=octarine.hq.xalasys.com
INPUTRC=/etc/inputrc
IRCNAME=franky
JAVA_HOME=/usr/java/j2sdk1.4.0
LANG=en_US
LDFLAGS=-s
LD_LIBRARY_PATH=/usr/lib/mozilla:/usr/lib/mozilla/plugins
LESSCHARSET=latin1
LESS=-edfMQ
LESSOPEN=|/usr/bin/lesspipe.sh %s
LEX=flex
LOCAL_MACHINE=octarine
LOGNAME=franky
LS_COLORS=no=00:fi=00:di=01;34:ln=01;36:pi=40;33:so=01;35:bd=40;33;01:cd=40;33;01:or=01;05;37;41:mi=01;05;37;41:ex=01;32:*.cmd=01;32:*.exe=01;32:*.com=01;32:*.btm=01;32:*.bat=01;32:*.sh=01;32:*.csh=01;32:*.tar=01;31:*.tgz=01;31:*.arj=01;31:*.taz=01;31:*.lzh=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.gz=01;31:*.bz2=01;31:*.bz=01;31:*.tz=01;31:*.rpm=01;31:*.cpio=01;31:*.jpg=01;35:*.gif=01;35:*.bmp=01;35:*.xbm=01;35:*.xpm=01;35:*.png=01;35:*.tif=01;35:
MACHINES=octarine
MAILCHECK=60
MAIL=/var/mail/franky
MANPATH=/usr/man:/usr/share/man/:/usr/local/man:/usr/X11R6/man
MEAN_MACHINES=octarine
MOZ_DIST_BIN=/usr/lib/mozilla
MOZILLA_FIVE_HOME=/usr/lib/mozilla
MOZ_PROGRAM=/usr/lib/mozilla/mozilla-bin
MTOOLS_FAT_COMPATIBILITY=1
MYMALLOC=0
NNTPPORT=119
NNTPSERVER=news
NPX_PLUGIN_PATH=/plugin/ns4plugin/:/usr/lib/netscape/plugins
OLDPWD=/nethome/franky
OS=Linux
PAGER=less
PATH=/nethome/franky/bin.Linux:/nethome/franky/bin:/usr/local/bin:/usr/local/sbin:/usr/X11R6/bin:/usr/bin:/usr/sbin:/bin:/sbin:.
PS1=\[\033[1;44m\]franky is in \w\[\033[0m\]
PS2=More input>
PWD=/nethome/franky
SESSION_MANAGER=local/octarine.hq.xalasys.com:/tmp/.ICE-unix/22106
SHELL=/bin/bash
SHELL_LOGIN=--login
SHLVL=2
SSH_AGENT_PID=22161
SSH_ASKPASS=/usr/libexec/openssh/gnome-ssh-askpass
SSH_AUTH_SOCK=/tmp/ssh-XXmhQ4fC/agent.22106
START_WM=twm
TERM=xterm
TYPE=type
USERNAME=franky
USER=franky
_=/usr/bin/printenv
VISUAL=vi
WINDOWID=20971661
XAPPLRESDIR=/nethome/franky/app-defaults
XAUTHORITY=/nethome/franky/.Xauthority
XENVIRONMENT=/nethome/franky/.Xdefaults
XFILESEARCHPATH=/usr/X11R6/lib/X11/%L/%T/%N%C%S:/usr/X11R6/lib/X11/%l/%T/%N%C%S:/usr/X11R6/lib/X11/%T/%N%C%S:/usr/X11R6/lib/X11/%L/%T/%N%S:/usr/X11R6/lib/X11/%l/%T/%N%S:/usr/X11R6/lib/X11/%T/%N%S
XKEYSYMDB=/usr/X11R6/lib/X11/XKeysymDB
XMODIFIERS=@im=none
XTERMID=
XWINHOME=/usr/X11R6
X=X11R6
YACC=bison -y

2.1.2. Variables locales

Les variables locales ne sont connues que dans le Shell actif. La commande intégrée set sans aucune option fait afficher une liste de toutes les variables (y compris les variables d'environnement ) et les fonctions. L'affichage sera trié et dans un format réutilisable.

Ci-dessous un fichier diff obtenu par comparaison entre l'affichage de printenv et de set, après l'avoir expurgé des fonctions qui sont aussi affichées par set:

franky ~> diff set.sorted printenv.sorted | grep "<" | awk '{ print $2 }'
BASE=/nethome/franky/.Shell/hq.xalasys.com/octarine.aliases
BASH=/bin/bash
BASH_VERSINFO=([0]="2"
BASH_VERSION='2.05b.0(1)-release'
COLUMNS=80
DIRSTACK=()
DO_FORTUNE=
EUID=504
GROUPS=()
HERE=/home/franky
HISTFILE=/nethome/franky/.bash_history
HOSTTYPE=i686
IFS=$'
LINES=24
MACHTYPE=i686-pc-linux-gnu
OPTERR=1
OPTIND=1
OSTYPE=linux-gnu
PIPESTATUS=([0]="0")
PPID=10099
PS4='+
PWD_REAL='pwd
SHELLOPTS=braceexpand:emacs:hashall:histexpand:history:interactive-comments:monitor
THERE=/home/franky
UID=504

Awk

L'outil GNU Awk est expliqué au Chapitre 6, Le langage de programmation GNU awk.

2.1.3. Variables typées selon leur contenu

A part distinguer les variables selon leur portée - locale/globale -, nous pouvons aussi les distinguer par catégories selon ce qu'elles contiennent. De ce point de vue, les variables sont de 4 types:

  • Variables de chaîne de caractères (NdT: nous dirons simplement "chaîne" par la suite)

  • Variables d'entier

  • Variables de constantes

  • Variables tableau

Nous traiterons ces types au Chapitre 10, Un peu plus sur les variables. Dans l'immédiat, nous allons travailler avec des valeurs de variables de type chaîne et entier.

2.2. Créer des variables

Les variables sont sensibles à la casse: minuscule/majuscule(majuscule en général). Donner des noms en minuscule aux variables locales est une convention parfois employée. Cependant, vous êtes libre de nommer comme vous voulez ou de mélanger la casse. Le nom peut aussi comprendre des chiffres, mais un nom commençant par un chiffre n'est pas admis:

prompt> export 1number=1
bash: export: `1number=1': not a valid identifier

Pour affecter une valeur dans un Shell, la commande est

VARNAME="value"

Laisser des espaces autour du signe égal causera une erreur. C'est conseillé d'entourer la valeur avec des guillemets lors de l'assignation: ça réduit les risques d'erreurs.

Divers exemples avec minuscules et majuscules, chiffres et espaces:

franky ~> MYVAR1="2"

franky ~7gt; echo $MYVAR1
2

franky ~> first_name="Franky"

franky ~> echo $first_name
Franky

franky ~> full_name="Franky M. Singh"

franky ~> echo $full_name
Franky M. Singh

franky ~> MYVAR-2="2"
bash: MYVAR-2=2: command not found

franky ~> MYVAR1 ="2"
bash: MYVAR1: command not found

franky ~> MYVAR1= "2"
bash: 2: command not found

franky ~> unset MYVAR1 first_name full_name

franky ~> echo $MYVAR1 $first_name $full_name
<--no output-->

franky ~>

2.3. Exporter les variables

Une variable créée comme celles ci-dessus est seulement visible par le Shell actif. C'est une variable locale: les processus enfants de ce Shell actif ne connaîtront pas cette variable. Afin de faire connaître ces variables à un sous-Shell, nous avons besoin de faire un export avec l'intégrée export. Les variables exportées sont appelées les variables d'environnement. Définir et exporter sont souvent 2 actions faites en même temps.

export VARNAME="valeur"

Un sous-Shell peut changer la valeur de variables héritées de son parent, mais cette modification n'affecte pas le parent. Cet exemple en fait la démonstration:

franky ~> full_name="Franky M. Singh"

franky ~> bash

franky ~> echo $full_name


franky ~> exit

franky ~> export full_name

franky ~> bash

franky ~> echo $full_name
Franky M. Singh

franky ~> export full_name="Charles the Great"

franky ~> echo $full_name
Charles the Great

franky ~> exit

franky ~> echo $full_name
Franky M. Singh

franky ~>

Quand d'abord on essaye de lire la valeur de full_name dans un sous-Shell, on n'a rien (echo affiche une chaîne nulle). Le sous-Shell finit, et full_name est exporté par le parent - une variable peut être exportée après qu'elle ait été assignée. Puis un nouveau sous-Shell est lancé, dans lequel la variable exportée par le parent est visible. Le contenu de la variable est changé, mais la valeur de cette variable pour le parent reste la même.

2.4. Variables réservées

2.4.1. Variables réservées du Bourne Shell

Bash utilise certaines variables Shell de la même manière que Bourne Shell. Dans certains cas, Bash assigne une valeur par défaut à la variable. La table ci-dessous donne un aperçu de ces variables Shell de base:

Tableau 3.1. Variables réservées Bourne Shell

Nom de variableDéfinition
CDPATHUne liste des répertoires, séparés par deux points(:), utilisés comme chemin de recherche pour l'intégrée cd.
HOMELe répertoire racine de l'utilisateur actif; le chemin par défaut pour l'intégrée cd. La valeur de cette variable est aussi utilisée par l'expansion du tilde
IFSUne liste de caractères qui peuvent séparer les champs; utilisé par Shell pour découper les mots lors du processus d'expansion.
MAILSi à ce paramètre est affecté un nom de fichier et que la variable MAILPATH n'est pas définie, Bash informe l'usager de l'arrivée d'un mail dans le fichier spécifié.
MAILPATHUne liste de fichiers, séparés par deux points(:), dont se sert le Shell régulièrement pour rechercher les nouveaux mails.
OPTARGLa valeur de l'argument de la dernière option traitée par l'intégrée getopts.
OPTINDLe rang de l'argument de la dernière option traitée par l'intégré getopts.
PATHUne liste de répertoires, séparés par deux points(:), dans lesquels le Shell recherche les commandes.
PS1La principale chaîne d'invite. La valeur par défaut est « '\s-\v\$ ' ».
PS2La seconde chaîne d'invite. La valeur par défaut est « '> ' ».

2.4.2. Les variables réservées de Bash

Ces variables sont définies ou utilisées par Bash, mais les autres Shells normalement ne les traitent pas spécialement.

Tableau 3.2. Les variables réservées de Bash

Nom de variableDéfinition
auto_resumeCette variable configure la façon dont le Shell interprète la saisie à la ligne de commande comme étant des ordres de contrôle de travaux.
BASHLe chemin complet où se trouve l'exécutable du Bash actif.
BASH_ENVSi cette variable est définie quand Bash est invoqué pour exécuter un script Shell, sa valeur est interprétée(expansion) et utilisée comme nom de fichier de démarrage à lire avant d'exécuter le script.
BASH_VERSIONLe numéro de version du Bash actif.
BASH_VERSINFOUn tableau en lecture dont chaque élément mémorise un niveau de la version du Bash actif.
COLUMNSUtilisé par l'intégrée select pour déterminer la largeur du terminal lors de l'affichage de listes de sélection. Automatiquement défini à la réception d'un signal SIGWINCH.
COMP_CWORDUn index dans ${COMP_WORDS} qui pointe sur le mot où se trouve le curseur.
COMP_LINELa ligne de commande courante.
COMP_POINTIndex qui point la position du curseur dans la commande courante.
COMP_WORDSUne variable tableau dont chaque élément renvoie un mot de la commande courante.
COMPREPLYUne variable tableau d'où Bash tire des interprétations possibles qui ont été générées par une fonction Shell dans le processus de génération.
DIRSTACKUne variable tableau mémorisant le contenu de la pile de répertoires.
EUIDLe nombre identifiant l'utilisateur actif.
FCEDITL'éditeur utilisé par défaut par l'option -e de l'intégrée fc.
FIGNOREUne liste de suffixes à ignorer, séparés par deux points (:), quand se produit la génération de noms de fichiers.
FUNCNAMEContient le nom de fonction si une fonction Shell est en train de s'exécuter.
GLOBIGNOREUne liste de patrons, séparés par deux points (:), qui sert à définir les fichiers à ignorer lors de la génération de nom de fichiers.
GROUPSUn tableau qui mémorise les groupes auxquels l'utilisateur appartient.
histcharsJusqu'à 3 caractères permettant de contrôler l'expansion d'historique, la substitution rapide, et le découpage en mots.
HISTCMDLe numéro d'historique, ou le rang dans la liste d'historique de la commande en cours.
HISTCONTROLDétermine si la commande en cours est ajoutée au fichier d'historique.
HISTFILELe nom de fichier dans lequel l'historique des commandes est conservé. La valeur par défaut est ~/.bash_history.
HISTFILESIZEDétermine le nombre maximum de lignes que mémorise le fichier d'historique; par défaut 500.
HISTIGNOREUne liste de patrons, séparés par deux points (:), qui sert à déterminer quelles commandes sont mémorisées dans l'historique.
HISTSIZEDétermine le nombre maximum de commandes que mémorise le fichier d'historique; par défaut 500.
HOSTFILEContient le nom d'un fichier au format de /etc/hosts qui devrait être lu quand le Shell a besoin du nom de machine hôte.
HOSTNAMEnom de la machine hôte.
HOSTTYPEChaîne de caractères décrivant la machine exécutant le Bash.
IGNOREEOFDétermine l'action du Shell quand il reçoit le caractère EOF et uniquement celui-là.
INPUTRCDélivre le nom du fichier d'initialisation de Readline, se substituant à /etc/inputrc.
LANGUtilisé pour tenter de déterminer le particularisme local lorsque qu'aucune variable commençant par LC_ ne spécifie la catégorie.
LC_ALLCette variable se substitue à LANG et à toute autre variable LC_ en spécifiant une catégorie de particularisme local.
LC_COLLATECette variable détermine l'ordre des lettres lors du tri du résultat de l'expansion des noms ainsi que le comportement des expressions des intervalles, des classes d'équivalences, et de la comparaison de chaînes lors de la recherche de motifs et l'expansion des noms de fichiers.
LC_CTYPECette variable détermine l'interprétation des caractères et le comportement des classes de caractères[NdT: ex: [:alpha] ] lors de l'expansion des noms de fichiers et de la recherche de patrons.
LC_MESSAGESCette variable détermine le particularisme utilisé pour traduire les chaînes entre guillemets précédés par un « $ ».
LC_NUMERICCette variable détermine la catégorie des particularismes employés pour formater les nombres.
LINENOLe numéro de la ligne en train d'être traitée dans le script ou la fonction Shell.
LINESUtilisé par l'intégrée select pour déterminer la longueur de colonne lors de l'affichage de listes de sélection.
MACHTYPEChaîne de caractères décrivant le type de système exécutant le Bash, sous la forme GNU CPU-COMPANY-SYSTEM. 
MAILCHECKIntervalle de temps (en secondes) entre 2 vérifications de présence de mail dans le fichier spécifié par MAILPATH ou MAIL.
OLDPWDContient le nom du répertoire précédent accédé par l'intégrée cd.
OPTERRSi défini à 1, Bash affiche les messages d'erreur générés par l'intégrée getopts.
OSTYPEUne chaîne décrivant le système d'exploitation sur lequel Bash s'exécute.
PIPESTATUSUn tableau contenant une liste des statuts d'exécution des processus les plus récemment exécutés en avant-plan (éventuellement une seule commande).
POSIXLY_CORRECTSi cette variable est définie quand bash démarre, le Shell entre en mode POSIX.
PPIDL'identifiant du process parent du Shell.
PROMPT_COMMANDDéfinie, la valeur est interprétée comme une commande à exécuter avant l'affichage de chaque invite (PS1).
PS3La valeur de cette variable est utilisée comme l'invite pour la commande select. Par défaut « '#? ' »
PS4La valeur est l'invite affichée avant que la commande soit affichée en echo quand l'option -x est activée; par defaut « '+ ' ».
PWDRenvoie le nom de répertoire courant défini par l'intégrée cd.
RANDOMChaque fois que cette variable est référencée, un entier entre 0 et 32767 est généré. Le fait d'assigner une valeur à cette variable réinitialise le générateur.
REPLYParamètre par défaut de l'intégrée read.
SECONDSRenvoie le nombre de secondes écoulées depuis que le Shell est lancé.
SHELLOPTSUne liste des options Shell activées, séparées par deux points(:).
SHLVLValeur augmentée de 1 chaque fois qu'une nouvelle instance de Bash est lancée.
TIMEFORMATCette valeur est un paramètre utilisé pour formater le résultat de chronométrage des instructions exécutées dans un tube(pipeline) lorsque le mot réservé time est spécifié.
TMOUTDéfini à une valeur supérieure à zéro, TMOUT est considéré comme le temps imparti maximum à l'intégrée read. Dans un Shell interactif, la valeur est considérée comme un nombre de secondes durant lesquelles une saisie est attendue. Bash se termine après ce laps de temps si aucune entrée n'est faite.
UIDLe nombre, le véritable identifiant, de l'utilisateur actif.

Consultez le man Bash, les pages info et doc pour de plus amples explications. Certaines variables sont en lecture seule, d'autres sont définies automatiquement et d'autres perdent leur sens initial quand elles sont redéfinies.

2.5. Paramètres Spéciaux

Le Shell considère certains paramètres spécifiquement. Ces paramètres ne peuvent qu'être référencés; leur affectation n'est pas permise.

Tableau 3.3. Les variables Bash spéciales

NomDéfinition
$*Est remplacé par tous les paramètres positionnels, sauf le premier $0. Quand l'expansion se produit entre guillemets, cela revient à avoir un seul mot avec la valeur de chaque paramètre séparée par le premier caractère de la variable spéciale IFS.
$@Est remplacé par tous les paramètres positionnels, sauf le premier $0. Quand l'expansion se produit entre guillemets, chaque paramètre est un mot à part entière.
$#Renvoie le nombre de paramètres positionnels en décimal.
$?Renvoie le statut d'exécution de l'instruction la plus récemment traitée en avant-plan dans un tube.
$-Renvoie les options déclarées lors de l'invocation de l'intégrée set, ou celles positionnées par le Shell lui-même (tel que -i).
$$Renvoie l'identifiant du process du Shell.
$!Renvoie l'identifiant du process de la commande la plus récemment exécutée en tâche de fond (asynchrone).
$0Renvoie le nom du Shell ou du script Shell actif.
$_Au démarrage du Shell, contient le nom complet du fichier exécutable actif - script ou Shell - tel que passé dans la liste d'arguments. Ensuite, renvoie le dernier argument de la commande précédente après expansion. Et aussi valorisé avant chaque exécution de commande avec la valeur du chemin complet de cette commande, puis exporté dans l'environnement d'exécution. A la vérification de présence de mails, ce paramètre contient le nom du fichier de mails.

Les paramètres positionnels sont les mots qui suivent le nom d'un script Shell. Ils définissent les variables $1, $2, $3 etc. Autant que nécessaire, ces variables sont ajoutées dans un tableau interne. $# mémorise le nombre de paramètres, comme démontré dans ce simple script:

#!/bin/bash

# positional.sh
# Ce script lit 3 paramètres positionnels et les affiche.

POSPAR1="$1"
POSPAR2="$2"
POSPAR3="$3"

echo "$1 est le premier paramètre positionnel, \$1."
echo "$2 est le deuxième paramètre positionnel, \$2."
echo "$3 est le troisième paramètre positionnel, \$3."
echo
echo "Le nombre total de paramètres positionnels est $#."

A l'exécution on peut donner autant de paramètres que l'on veut:

franky ~> positional.sh un deux trois quatre cinq
un est le premier paramètre positionnel, $1.
deux est le deuxième paramètre positionnel, $2
trois est le troisième paramètre positionnel, $3.

Le nombre total de paramètres positionnels est 5.

franky ~> positional.sh un deux
un est le premier paramètre positionnel, $1.
 deux est le deuxième paramètre positionnel, $2
 est le troisième paramètre positionnel, $3.

Le nombre total de paramètres positionnels est 2

Plus de précisions sur l'évaluation de ces paramètres au Chapitre 7, Les instructions de condition et à la Section 7, « L'intégrée shift ».

Quelques exemples sur les autres paramètres spéciaux:

franky ~> grep dictionary /usr/share/dict/words
dictionary

franky ~> echo $_
/usr/share/dict/words

franky ~> echo $$
10662

franky ~> mozilla &
[1] 11064

franky ~> echo $!
11064

franky ~> echo $0
bash

franky ~> echo $?
0

franky ~> ls doesnotexist
ls: doesnotexist: No such file or directory

franky ~> echo $?
1

franky ~>

L'utilisateur franky lance la commande grep, qui a pour effet la valorisation de la variable _. l'ID du processus de son Shell est 10662. Après avoir mis un travail en tâche de fond, la variable ! renvoie l'ID du processus du travail en tâche de fond. Le Shell actif est bash. Quand une erreur se produit, ? renvoie un statut d'exécution différent de 0 (zéro).

2.6. Script à finalités multiples grâce aux variables

En plus de rendre le script plus lisible, les variables vous permettent d'utiliser un même script dans divers environnements ou pour des finalités multiples. Prenez l'exemple suivant, un script très simple qui effectue une sauvegarde du répertoire racine de frankyvers un serveur distant:

#!/bin/bash

# Ce script fait une sauvegarde de mon répertoire personnel.

cd /home

# Ceci crée le fichier archive
tar cf /var/tmp/home_franky.tar franky > /dev/null 2>&1

# Avant supprimer l'ancien fichier bzip2.  Redirige les erreurs parce que ceci en génère quand l'archive
# n'existe pas.  Puis crée un nouveau fichier compressé.
rm /var/tmp/home_franky.tar.bz2 2> /dev/null
bzip2 /var/tmp/home_franky.tar

# Copie le fichier vers un autre hôte - nous avons une clé ssh pour effectuer ce travail sans intervention.
scp /var/tmp/home_franky.tar.bz2 bordeaux:/opt/backup/franky > /dev/null 2>&1

# Crée un marqueur temporel dans un fichier journal..
date > /home/franky/log/home_backup.log
echo backup succeeded > /home/franky/log/home_backup.log

Avant tout, vous avez plus tendance à faire des erreurs si vous saisissez au clavier les noms de fichiers et de répertoires chaque fois que nécessaire. De plus supposez que franky veuille donne ce script à carol, alors carol aura à faire des modifications par l'éditeur avant de pouvoir sauvegarder son répertoire. De même si franky veut se servir du script pour sauvegarder d'autres répertoires. Pour une réutilisation aisée, transformer tous les fichiers, répertoires, nom d'utilisateur, nom d'hôte, etc. en variables. Ainsi, vous n'avez besoin que de modifier la variable une fois, et non pas de modifier chaque occurrence de la chaîne correspondante tout au long du script. Voici un exemple:

#!/bin/bash
                                                                                                 
# Ce script fait une sauvegarde de mon répertoire racine.

# Modifier les valeurs des variables pour que le script tourne pour vous:
BACKUPDIR=/home
BACKUPFILES=franky
TARFILE=/var/tmp/home_franky.tar
BZIPFILE=/var/tmp/home_franky.tar.bz2
SERVER=bordeaux
REMOTEDIR=/opt/backup/franky
LOGFILE=/home/franky/log/home_backup.log

cd $BACKUPDIR

# Ceci crée le fichier d'archive
tar cf $TARFILE $BACKUPFILES > /dev/null 2>&1
                                                                                                 
# D'abord supprimer l'ancien fichier bzip2.  Redirige les erreurs parce que ceci en génère quand l'archive
# n'existe pas.  Puis crée un nouveau fichier compressé.
rm $BZIPFILE 2> /dev/null
bzip2 $TARFILE

# Copie le fichier vers un autre hôte - nous avons une clé ssh pour effectuer ce travail sans intervention.
scp $BZIPFILE $SERVER:$REMOTEDIR > /dev/null 2>&1

# Crée un marqueur temporel dans un fichier journal..
date > $LOGFILE
echo backup succeeded > $LOGFILE

Répertoires volumineux et faible bande passante

Tout le monde peut comprendre l'exemple ci-dessus, en utilisant un répertoire réduit et un hôte de son sous-réseau. En fonction de votre bande passante, de la taille du répertoire et de l'endroit du serveur distant, cela peut prendre un temps terriblement long de faire la sauvegarde. Pour les répertoires les plus volumineux et une bande passante faible, employez rsync pour garder les répertoires synchronisés entre les 2 machines.

3. Echappement et protection de caractères

3.1. Pourquoi protéger ou 'échapper' un caractère?

Certaines touches ont un sens spécial dans un certain contexte. La protection - ou encore citation - est utilisée pour s'échapper du sens spécial de ces caractères ou mots: en d'autres termes l'échappement peut désactiver le comportement spécial de ces caractères, il peut empêcher les mots réservés d'être reconnus comme tel et il peut désactiver l'expansion de paramètres.

3.2. Le caractère Echap (escape)

Le caractère Echap sert à protéger la signification spéciale d'un caractère unique. Le slash inversé sans guillemets, \, est utilisé comme caractère Echap dans Bash. Il préserve le sens littéral du caractère le suivant, à l'exception de saut de ligne. Si un caractère 'saut de ligne' apparaît juste après le slash inversé, cela marque la continuation de la ligne quand elle est plus longue que la largeur du terminal; le slash inversé est ôté du flot entré et donc en fait ignoré.

franky ~> date=20021226

franky ~> echo $date
20021226

franky ~> echo \$date
$date

Dans cet exemple, la variable date est définie avec une valeur. Le premier echo affiche la valeur de la variable, mais dans le second le signe $ est protégé.

3.3. Les apostrophes

Les apostrophes (') sont utilisées pour préserver la valeur littérale des caractères enfermés entre apostrophes. Une apostrophe ne peut pas être enfermée entre apostrophes, même si elle est précédée par un slash inversée.

Continuons avec l'exemple précédent:

franky ~> echo '$date'
$date

3.4. Les guillemets

Avec les guillemets la valeur littérale de tous les caractères est préservée, sauf pour le $, les apostrophes inversées (``) et le slash inversé.

Le $ et `` conservent leur sens spécial à l'intérieur de guillemets.

Le slash inversé conserve son sens seulement quand il est suivi de $, ``, ", \, et 'saut de ligne'. Au sein de guillemets, les \ sont éliminés du flot entré quand il est suivi d'un de ces caractères. Le \ qui précède les caractères sans sens spécial est laissé en l'état pour être interprété par le Shell.

Un guillemet peut être protégé à l'intérieur de guillemets en le faisant précéder par \.

franky ~> echo "$date"
20021226

franky ~> echo "`date`"
Sun Apr 20 11:22:06 CEST 2003

franky ~> echo "I'd say: \"Go for it!\""
I'd say: "Go for it!"

franky ~> echo "\"
More input>"

franky ~> echo "\\"
\

3.5. Codage ANSI-C

Les mots de la forme « $'MOT' » sont traités d'une manière spéciale. Le mot se transforme en une chaîne, avec le caractère Echap slash inversé remplacé comme spécifié dans le standard ANSI-C. La séquence d'échappement du slash inversé peut être trouvée dans la documentation Bash.

3.6. Particularités

Une chaîne entre guillemets précédée par un $ sera traitée selon la norme en vigueur. Si cette norme est celle de « C » ou celle de « POSIX », le $ est ignoré. Si la chaîne est transposée avec remplacement, le résultat est entre guillemets.

4. Le processus d'expansion de Shell

4.1. Généralité

Après que la commande ait été décomposée en éléments (voir la Section 4.1.1, « La syntaxe Shell »), ces éléments ou mots sont interprétés ou autrement dit résolus. Il y a 8 sortes d'expansion effectuées, lesquelles vont être traitées dans les sections suivantes dans l'ordre où le processus opère.

Après toutes les sortes d'expansions effectuées, guillemets et apostrophes sont éliminés.

4.2. L'expansion d'accolades

L'expansion d'accolade est un mécanisme par lequel des chaînes peuvent être arbitrairement générées. Les patrons sujets à expansion prennent la forme d'un préfixe optionnel, suivi d'une série de chaînes séparées par des virgules, le tout à l'intérieur d'accolades, suivi par un suffixe optionnel. Le préfixe enrichit chaque chaîne au début, puis à son tour le suffixe enrichit la fin, résultant en une expansion de gauche à droite.

L'expansion d'accolades peut être imbriquée. Le résultat des chaînes ainsi obtenues n'est pas trié; l'ordre de gauche à droite est préservé.

franky ~> echo sp{el,il,al}l
spell spill spall

L'expansion d'accolade est effectuée avant tout autres, et tout caractère spécial en vue d'un autre type d'expansion est préservé dans ce résultat. C'est strictement textuel. Bash n'applique aucune interprétation syntaxique au contexte de l'expansion ou au texte entre accolades. Pour éviter des conflits avec l'expansion de paramètres, la chaîne « ${ » n'est pas éligible à l'expansion d'accolade.

Une forme correcte d'expansion d'accolades doit contenir une accolade ouvrante et fermante non protégée, et au moins une virgule non protégée. Toute forme d'expansion d'accolade incorrecte est laissée telle quelle.

4.3. L'expansion du tilde

Si un mot commence par un tilde non protégé (« ~ »), tous les caractères jusqu'au premier slash non-protégé (ou tous les caractères si il n'y a pas de slash non-protégé) sont considérés comme un préfixe tilde. Si aucun des caractères dans le préfixe tilde n'est protégé, ces caractères qui suivent le tilde sont considérés comme un nom de connection possible. Si ce nom de connection est la chaîne nulle, le tilde est remplacé par la valeur de la variable Shell HOME. Si HOME n'est pas défini, le répertoire racine de l'utilisateur exécutant le Shell est utilisé à la place. Sinon, le préfixe tilde est remplacé par le répertoire racine associé au nom de connection spécifié.

Si le préfixe tilde est « ~+ », la valeur de la variable Shell PWD remplace le préfixe tilde. Si le préfixe tilde est « ~- », la valeur de la variable Shell OLDPWD, si définie, s'y substitue.

Si les caractères suivant le tilde dans le préfixe consistent en un nombre N, optionnellement préfixé par « + » ou « - », le préfixe tilde est remplacé par l'élément correspondant dans la pile de répertoire, comme il serait affiché par l'intégrée dirs invoquée avec, comme argument, le caractère suivant le tilde dans le préfixe tilde. Si le préfixe tilde, sans le tilde, consiste en un nombre sans signe « + » ou « - », « + » est implicite.

Si le nom de connection est invalide, ou si l'expansion de tilde échoue, le mot est laissé tel quel.

Chaque assignation de variable donne lieu à un contrôle sur la présence d'un préfixe tilde non-protégé qui suit immédiatement un « : » ou un « = ». Dans ce cas l'expansion du tilde se produit. Par conséquent, on peut utiliser un nom de fichier avec tilde dans PATH, MAILPATH, et CDPATH, et le Shell utilise l'expansion du nom.

Exemple:

franky ~> export PATH="$PATH:~/testdir"

~/testdir sera interprété en $HOME/testdir, donc si $HOME est /var/home/franky, le répertoire /var/home/franky/testdir sera ajouté au contenu de la variable PATH.

4.4. Paramètre Shell et expansion de variable

Le caractère « $ » introduit l'expansion de paramètre, la substitution de commande ou l'expansion arithmétique. Le nom du paramètre - ou symbole - à interpréter peut être enchâssé entre accolades. Elles sont optionnelles mais utiles à la séparation des caractères du symbole à interpréter de ceux suivant immédiatement.

Quand l'accolade est utilisée, le premier « } » - non protégé par un slash inversé ou ni à l'intérieur d'une chaîne entre guillemet, ni à l'intérieur d'une expansion arithmétique incorporée ou d'une substitution de commande ou d'expansion de paramètre - est le signal fermant correspondant.

La forme basique de l'expansion de paramètre est « ${PARAMETRE} ». La valeur de « PARAMETRE » y est substituée. Les accolades sont requises quand « PARAMETRE » est un paramètre positionnel avec un symbole de plus de 1 caractère, ou quand « PARAMETRE » est suivi par un caractère qui ne doit pas être interprété comme faisant parti du symbole.

Si le premier caractère de « PARAMETRE » est un point d'exclamation, Bash considère les caractères suivants de « PARAMETRE » comme étant le symbole de la variable; cette variable est alors interprétée et le résultat est utilisé dans la suite de la substitution, plutôt que la valeur de « PARAMETRE » lui-même. Ceci est connu sous le nom d'expansion indirecte.

Vous êtes certainement familier avec l'expansion de paramètre directe, parce qu'elle est fréquente même dans les cas les plus simples, tel que celui ci-dessus ou le suivant:

franky ~> echo $SHELL
/bin/bash

Voici un exemple d'expansion indirecte:

franky ~> echo ${!N*}
NNTPPORT NNTPSERVER NPX_PLUGIN_PATH

Notez que cela ne donne pas la même chose que echo $N*.

La construction suivante permet la création du nom de variable si il n'existe pas:

${VAR:=value}

Exemple:

franky ~> echo $FRANKY

franky ~> echo ${FRANKY:=Franky}
Franky

Cependant, les paramètres spéciaux, dont les paramètres positionnels, ne doivent pas être affectés par ce biais.

Nous approfondirons l'utilisation de l'accolade dans le traitement des variables au Chapitre 10, Un peu plus sur les variables. Les pages info de Bash fournissent aussi d'autres informations.

4.5. La substitution de commande

La substitution de commande permet de remplacer la commande elle-même par son résultat. La substitution de commande survient quand une commande est enchâssée ainsi:

$(commande)

ou ainsi avec les apostrophes inversées:

`commande`

Bash effectue l'expansion en exécutant COMMANDE et en la remplaçant par son résultat, avec tous les sauts de lignes éliminés. Les sauts de ligne incorporés(NdT: au résultat de la commande) ne sont pas éliminés, mais ils peuvent l'avoir été pendant le découpage en mot.

franky ~> echo `date`
Thu Feb 6 10:06:20 CET 2003

Quand l'ancien signal de substitution - l'apostrophe inversée - est utilisé, le slash inversé conserve son sens littéral sauf si il est suivi de « $ », « ` », ou « \ ». La première apostrophe inversée non précédée d'un slash inversé termine la commande de substitution. Quand la forme « $(COMMANDE) » est utilisée, tous les caractères entre parenthèses font partis de la commande; aucun n'est traité spécifiquement.

Une substitution de commande peut être incorporée à une autre. Pour en incorporer dans la forme apostrophes inversées, protéger l'apostrophe la plus interne avec des slashs inversés.

Si la substitution apparaît entre guillemets, le découpage en mots et l'expansion de noms de fichiers ne sont pas effectués sur les résultats.

4.6. L'expansion arithmétique

L'expansion arithmétique permet l'évaluation d'une expression arithmétique et sa substitution par le résultat. Le format pour l'expansion arithmétique est:

$(( EXPRESSION ))

L'expression est traitée comme si elle était entre guillemets, mais un guillemet à l'intérieur des parenthèses n'est pas traité spécifiquement. Tous les mots de l'expression font l'objet d'expansion de paramètre, de substitution de commande, et d'élimination d'apostrophe. Une substitution arithmétique peut être incorporée à une autre.

L'évaluation d'une expression arithmétique est faite en entiers de taille fixe sans contrôle de dépassement - bien que la division par zéro soit détectée comme une erreur. Les opérateurs sont à peu près les mêmes que dans le langage de programmation C. Par ordre de priorité décroissante, la liste ressemble à ceci

Tableau 3.4. Opérateurs arithmétiques

Opérateursens
[] ++VAR and --VARvariable: post-incrément et post-décrément
++VAR and --VARvariable: pré-incrément et pré-décrément
- et +moins et plus
! et ~ négation logique et bit à bit
**exponentiation
*, / et %multiplication, division, reste
+ et -addition, soustraction
<< and >>Décalage des bits à gauche ou à droite
<=, >=, < et >opérateurs de comparaison
== et !=égalité et inégalité
&ET logique
^OU logique exclusif
|OU logique
&&ET logique
||OU logique
expr ? expr : exprévaluation conditionnelle
=, *=, /=, %=, +=, -=, <<=, >>=, &=, ^= et |=affectations
,séparateur entre expressions

Les variables Shell sont autorisées comme opérandes; l'expansion de paramètre est effectuée avant l'évaluation de l'expression. Dans une expression, les variables Shell peuvent aussi être référencées par le nom sans utiliser la syntaxe d'expansion de paramètre. La valeur d'une variable est évaluée en tant qu'expression arithmétique quand elle est référencée. Une variable Shell doit avoir l'attribut 'entier' positionné pour être utilisée dans une expression.

Une constante commençant par un 0 (zéro) est considérée comme un chiffre octal. Un « 0x » ou « 0X » au début marque l'hexadécimal. Sinon, un nombre prend la forme « [BASE'#']N », où « BASE » est un nombre décimal entre 2 et 64 représentant la base arithmétique, et N un nombre dans cette base. Si « BASE'#' » est omis, alors la base 10 est utilisée. Les chiffres supérieurs à 9 sont représentés par les minuscules, les majuscules, « @ », et « _ », dans cet ordre. Si « BASE » est inférieur ou égale à 36, les minuscules et les majuscules sont interchangeables dans leur représentation des chiffres entre 10 et 35.

Les opérateurs sont évalués par ordre de priorité. Les sub-expressions entre parenthèses sont évaluées d'abord ce qui peut prévaloir sur l'ordre de priorité ci-dessus.

Autant que possible, les utilisateurs de Bash devraient essayer d'utiliser la syntaxe avec les crochets:

$[ EXPRESSION ]

Cependant, ceci ne fait qu'évaluer l'EXPRESSION, et ne teste pas:

franky ~> echo $[365*24]
8760

Voir Section 1.2.2, « Comparaisons numériques », entre autres, pour des exemples pratiques de scripts.

4.7. La substitution de processus

La substitution de processus est effectuée par les systèmes qui admettent les tubes(pipes) nommés (FIFO: NdT=First In First Out=premier entré, premier sorti) ou la méthode /dev/fd de nommage de fichiers ouverts. Ca se présente sous la forme de

<(LIST)

ou

>(LIST)

Le processus LIST est exécuté avec ses entrées et sorties connectées à un tube ou des fichiers dans /dev/fdx. Le nom de ce fichier(NdT: contenu dans /dev/fdx) passé en argument à la commande courante est le résultat après expansion. Si la forme « >(LIST) » est employée, écrire dans le fichier a pour effet d'alimenter l'entrée de LIST. Si la forme « <(LIST) » est employée, le fichier passé en argument devrait être lu pour obtenir la sortie de LIST. Notez qu'aucun espace ne doit apparaître entre le signe < ou > et la parenthèse gauche, sinon la construction serait interprétée comme une redirection.

Quand la substitution de processus est possible, elle est effectuée simultanément avec l'expansion de variable, la substitution de commande, et l'expansion arithmétique.

Plus de détails à la Section 2.3, « Redirection et descripteurs de fichiers ».

4.8. Le découpage de mots

Le Shell recherche dans le résultat de l'expansion de paramètre, de la substitution de commande, et de l'expansion arithmétique des mots qui n'ont pas été interprétés du fait des guillemets.

Le Shell traite chaque caractère de $IFS comme un délimiteur, et découpe le résultat des autres expressions en mots sur la base de ces caractères. Si IFS n'est pas déclaré, ou si il vaut exactement « '<space><tab><newline>' », sa valeur par défaut, alors toute suite de caractères IFS servent à délimiter les mots. Si IFS a une valeur autre que celle par défaut, alors les suites d'« espace » et « Tab » sont ignorées au début et à la fin du mot, du moment que l'espace est inclut dans IFS (un caractère espace IFS). Tout caractère dans IFS, qui n'est pas un espace IFS, accolé à un caractère espace IF délimite un champs. Une suite de caractère espace IFS est aussi traitée comme un délimiteur. Si la valeur de IFS est nulle, le découpage en mots n'intervient pas.

Un argument vide(« "" » ou « '' ») est conservé. Un argument ayant une valeur nulle, suite à l'expansion d'un paramètre, est éliminé. Si un paramètre non valorisé est interprété à l'intérieur de guillemets, il en résulte un argument nul qui est conservé.

Expansion et découpage en mots

Si aucune expansion ne se produit, aucun découpage n'est effectué

4.9. Expansion de noms de fichier

Après le découpage en mots, à moins que l'option -f ait été utilisée (voir Section 3.2, « Débugger qu'une partie du script »), Bash scanne chaque mot pour les caractères « * », « ? », and « [ ». Si l'un de ces caractères apparaît, alors le mot est considéré comme étant un PATRON, et est remplacé par la liste des noms de fichiers correspondants au patron triée par ordre alphabétique. Si aucun nom de fichier ne correspond, et que l'option Shell nullglob est désactivée, le mot est laissé en l'état. Si l'option nullglob est activée, et qu'aucune correspondance n'est trouvée, le mot est éliminé. Si l'option Shell nocaseglob est activée, la correspondance est recherchée sans considérer la casse des caractères alphabétiques.

Quand un patron sert à la génération de noms de fichiers, le caractère « . » au début d'un nom de fichier ou immédiatement après un slash doit trouver une correspondance explicitement, à moins que l'option Shell dotglob soit activée. Lors de la recherche de correspondance de noms de fichiers, le caractère slash doit toujours être explicitement indiqué. Dans les autres cas, le caractère « . » n'est pas traité spécifiquement.

La variable Shell GLOBIGNORE peut être utilisée pour restreindre l'ensemble de fichiers en correspondance avec le patron. Si GLOBIGNORE est activé , les noms qui correspondent à l'un des patrons dans GLOBIGNORE sont retirés de la liste de correspondance. Les noms de fichiers . et .. sont toujours ignorés, même si GLOBIGNORE est activé. Cependant, déclarer GLOBIGNORE a pour effet d'activer l'option Shell dotglob , donc tous les autres fichiers commençant par « . » correspondront. Pour garder la possibilité d'ignorer les fichiers commençant par « . », indiquer « .* » comme étant un des patrons à ignorer dans GLOBIGNORE. L'option dotglob est désactivé quand GLOBIGNORE n'est pas déclaré.

5. Alias

5.1. Que sont les alias?

Un alias permet de substituer un mot à une chaîne de caractère quand il est utilisé comme premier mot d'une commande simple. Le Shell maintient une liste d'alias qui sont déclarés ou invalidés avec les commandes alias et unalias. Saisir alias sans options pour afficher une liste des alias connus du Shell courant.

franky: ~> alias
alias ..='cd ..'
alias ...='cd ../..'
alias ....='cd ../../..'
alias PAGER='less -r'
alias Txterm='export TERM=xterm'
alias XARGS='xargs -r'
alias cdrecord='cdrecord -dev 0,0,0 -speed=8'
alias e='vi'
alias egrep='grep -E'
alias ewformat='fdformat -n /dev/fd0u1743; ewfsck'
alias fgrep='grep -F'
alias ftp='ncftp -d15'
alias h='history 10'
alias fformat='fdformat /dev/fd0H1440'
alias j='jobs -l'
alias ksane='setterm -reset'
alias ls='ls -F --color=auto'
alias m='less'
alias md='mkdir'
alias od='od -Ax -ta -txC'
alias p='pstree -p'
alias ping='ping -vc1'
alias sb='ssh blubber'
alias sl='ls'
alias ss='ssh octarine'
alias sss='ssh -C server1.us.xalasys.com'
alias sssu='ssh -C -l root server1.us.xalasys.com'
alias tar='gtar'
alias tmp='cd /tmp'
alias unaliasall='unalias -a'
alias vi='eval `resize`;vi'
alias vt100='export TERM=vt100'
alias which='type'
alias xt='xterm -bg black -fg white &'

franky ~>

Les alias sont utiles pour spécifier une version par défaut d'une commande qui existe en plusieurs versions sur le système, ou pour spécifier les options par défaut d'une commande. Un autre emploi des alias est de permettre la correction des fautes de frappes.

Le premier mot de chaque commande simple, si il n'est pas entre guillemets, est recherché dans la liste des alias. Si il y est, ce mot est remplacé par le texte correspondant. Le nom d'alias et le texte correspondant peut contenir tout caractère Shell valide, y compris les métacaractères, avec l'exception que le nom d'alias ne doit pas contenir « = ». Le premier mot du texte correspondant est recherché dans les alias, mais si ce mot est le même que celui traité il n'est pas remplacé une deuxième fois. Ceci signifie qu'on peut déclarer ls équivalent à ls -F, par exemple, et Bash n'essayera pas de remplacer récursivement l'alias trouvé. Si le dernier caractère de la valeur de l'alias est un espace ou une tabulation, alors le mot suivant de la commande après l'alias est aussi recherché dans les alias.

Les alias ne sont pas remplacés quand le Shell n'est pas interactif, sauf si l'option expand_aliases est activée par l'intégrée shopt.

5.2. Créer et supprimer des alias

Un alias est créé par l'intégrée alias. Pour une déclaration permanente, ajouter la commande alias dans l'un de vos scripts d'initialisation; si vous l'entrez seulement sur la ligne de commande, il sera connu que durant la session.

franky ~> alias dh='df -h'

franky ~> dh
Filesystem            Size  Used Avail Use% Mounted on
/dev/hda7             1.3G  272M 1018M  22% /
/dev/hda1             121M  9.4M  105M   9% /boot
/dev/hda2              13G  8.7G  3.7G  70% /home
/dev/hda3              13G  5.3G  7.1G  43% /opt
none                  243M     0  243M   0% /dev/shm
/dev/hda6             3.9G  3.2G  572M  85% /usr
/dev/hda5             5.2G  4.3G  725M  86% /var

franky ~> unalias dh

franky ~> dh
bash: dh: command not found

franky ~>

Bash lit toujours au moins une ligne complète saisie avant d'exécuter une des commandes de cette ligne. L'alias est interprété quand la commande est lue, non pas quand elle est exécutée. De ce fait, une définition d'alias apparaissant sur la même ligne qu'une autre commande ne prendra effet qu'à la lecture de la ligne suivante. Les commandes suivant la définition de l'alias sur la ligne ne seront pas affectées par le nouvel alias. Ce comportement joue aussi quand une fonction est exécutée. Un alias est interprété quand la définition d'une fonction est lue, pas quand la fonction est exécutée, parce que la définition de fonction est elle-même une commande composée. En conséquence, l'alias définit dans une fonction n'est pas utilisable tant que la fonction n'a pas été exécutée. En toute sécurité, toujours définir les alias sur des lignes séparées, et ne pas employer alias dans des commandes composées.

Les processus enfants n'héritent pas des alias. Bourne shell (sh) ne reconnaît pas les alias.

Plus sur les fonctions au Chapitre 11, Fonctions.

Les fonctions sont plus rapides

Les alias sont recherchés après les fonctions et donc leur résolution est plus lente. Alors que les alias sont plus faciles à comprendre, les fonctions Shell sont préférées aux alias pour la plupart des usages.

6. Plus d'options Bash

6.1. Afficher les options

Nous avons déjà abordé un certain nombre d'options Bash utiles à la correction des scripts. Dans cette section, nous aurons une vue plus approfondie des options Bash.

Utilisez l'option -o de set pour afficher toutes les options Shell:

willy:~> set -o
allexport		off
braceexpand		on
emacs			on
errexit			off
hashall			on
histexpand		on
history			on
ignoreeof		off
interactive-comments	on
keyword			off
monitor			on
noclobber		off
noexec			off
noglob			off
nolog			off
notify			off
nounset			off
onecmd			off
physical		off
posix			off
privileged		off
verbose			off
vi			off
xtrace			off

Voir les pages Bash info, section Shell Built-in CommandsThe Set Built-in pour une description de chaque option. Beaucoup d'options ont un raccourci de un caractère: l'option xtrace , par exemple, équivaut à spécifier set -x.

6.2. Changer les options

Les options Shell peuvent être modifiées soit par rapport à celles par défaut à l'appel du Shell, soit au cours des traitements Shell. Elles peuvent être aussi intégrées aux fichiers de configuration des ressources Shell.

La commande suivante exécute un script en mode compatible POSIX:

willy:~/scripts> bash --posix script.sh

Pour changer l'environnement temporairement, ou à l'usage d'un script, nous utiliserions plutôt set. Use - (moins) pour activer l'option, + pour la désactiver:

willy:~/test> set -o noclobber

willy:~/test> touch test

willy:~/test> date > test
bash: test: cannot overwrite existing file

willy:~/test> set +o noclobber

willy:~/test> date > test

L'exemple ci-dessus montre l'usage de l'option noclobber , qui évite que les fichiers existants soient écrasés par les opérations de redirection. La même chose joue pour les options à 1 caractère, par exemple -u, qui, activée, traite les variables non déclarées comme des erreurs, et quitte un Shell non-interactif quand survient une telle erreur:

willy:~> echo $VAR


willy:~> set -u

willy:~> echo $VAR
bash: VAR: unbound variable

Cette option est aussi utile pour détecter des valeurs incorrectes affecées à des variables: la même erreur se produira aussi, par exemple,quand une chaîne de caractère est affectée à une variable qui a été déclarée explicitement comme devant contenir une valeur numérique.

Voici un dernier exemple qui illustre l'option noglob , laquelle empêche les caractères spéciaux d'être interprétés:

willy:~/testdir> set -o noglob

willy:~/testdir> touch *

willy:~/testdir> ls -l *
-rw-rw-r--    1 willy    willy		0 Feb 27 13:37 *

7. Résumé

L'environnement Bash peut être configuré globalement et pour chaque utilisateur. Divers fichiers de configuration servent à régler précisément le comportement du Shell.

Ces fichiers contiennent des options Shell, des déclarations de variables, des définitions de fonctions et diverses autres constructions qui nous permettent d'adapter notre environnement.

Mis à part les mots réservés par Bourne Shell, Bash et les paramètres spéciaux, les noms de variables peuvent être donnés assez librement.

Parce que beaucoup de caractères ont un double, voire triple, sens, selon l'environnement, Bash utilise une syntaxe appropriée pour inhiber le sens spécial de un ou plusieurs caractères quand le traitement particulier n'est pas désiré.

Bash emploie diverses méthodes pour l'expansion de la ligne de commande afin de déterminer quelle est la commande à exécuter.

8. Exercices

Pour cet exercice, vous aurez besoin de lire les pages man de useradd, parce que nous allons utiliser le répertoire /etc/skel pour stocker les fichiers de configuration Shell par défaut, lesquels sont copiés dans le répertoire racine de chaque utilisateur ajouté.

D'abord nous ferons quelques exercices de portée générale sur la déclaration et l'affichage de variables.

  1. Créer 3 variables, VAR1, VAR2 et VAR3; les initialiser respectivement aux valeurs « thirteen », « 13 » et « Happy Birthday ».

  2. Faire afficher les valeurs des ces 3 variables.

  3. Sont-elles des variables locales ou globales?

  4. Supprimer VAR3.

  5. Pouvez-vous voir les 2 variables restantes dans un nouveau terminal?

  6. Modifier /etc/profile pour que tous les utilisateurs soient accueillis à la connection (tester).

  7. Pour le compte root, modifier l'invite pour que s'affiche « Danger!! root travaille en mode \w », de préférence une couleur vive telle que rouge ou rose ou le mode vidéo inversé.

  8. Assurez-vous que les utilisateurs nouvellement créés ont aussi une invite personnalisée qui les informe sur quel système et dans quel répertoire ils travaillent. Testez vos modifications en ajoutant un utilisateur et en se connectant avec ce compte.

  9. Ecrire un script dans lequel 2 entiers sont assignés à 2 variables. Le script doit calculer la surface d'un rectangle à partir de ces valeurs. Il devrait être aéré avec des commentaires et générer un affichage plaisant.

N'oubliez pas le chmod de vos scripts!