<chapter id="chap_03"><title>L'environnement du Bash</title>
<abstract>
<para>Dans ce chapitre nous traiterons des diverses façons de modifier l'environnement du Bash&nbsp;:</para>
<para><itemizedlist>
<listitem><para>En modifiant les fichiers d'initialisation du Shell</para></listitem>
<listitem><para>En utilisant des variables</para></listitem>
<listitem><para>En utilisant divers modes d'échappement</para></listitem>
<listitem><para>En effectuant des calculs arithmétiques</para></listitem>
<listitem><para>En déclarant des alias</para></listitem>
<listitem><para>En employant l'expansion et la substitution</para></listitem>
</itemizedlist></para>
</abstract>
<sect1 id="sect_03_01"><title>Les fichiers d'initialisation du Shell</title>

<sect2 id="sect_03_01_01"><title>Les fichiers de configuration qui agissent sur tout le système</title>
<sect3 id="sect_03_01_01_01"><title>/etc/profile</title>
<para>Quand il est invoqué<indexterm><primary>configuration files</primary><secondary>/etc/profile</secondary></indexterm> interactivement avec l'option <option>--login</option> ou si il est invoqué en tant que <command>sh</command>, Bash lit les instructions de  <filename>/etc/profile</filename>.  Ceci habituellement définit les variables Shell <varname>PATH<indexterm><primary>variables</primary><secondary>PATH</secondary></indexterm></varname>, <varname>USER<indexterm><primary>variables</primary><secondary>USER</secondary></indexterm></varname>, <varname>MAIL<indexterm><primary>variables</primary><secondary>MAIL</secondary></indexterm></varname>, <varname>HOSTNAME<indexterm><primary>variables</primary><secondary>HOSTNAME</secondary></indexterm></varname> et <varname>HISTSIZE<indexterm><primary>variables</primary><secondary>HISTSIZE</secondary></indexterm></varname>.</para>
<para>Sur certains systèmes la valeur <command>umask</command> est définie dans  <filename>/etc/profile</filename>&nbsp;; sur d'autres ce fichier indique d'autres fichiers de configuration tels que&nbsp;:</para>
<itemizedlist>
<listitem><para><filename>/etc/inputrc<indexterm><primary>configuration files</primary><secondary>/etc/inputrc</secondary></indexterm></filename>, le fichier d'initialisation du système Readline où vous pouvez configurer le style de son de la ligne de commande.</para></listitem>
<listitem><para>le répertoire <filename>/etc/profile.d</filename><indexterm><primary>configuration files</primary><secondary>/etc.profile.d</secondary></indexterm>, qui contient les fichiers configurant le comportement de programmes spécifiques dans tout le système.</para></listitem>
</itemizedlist>
<para>Tous les paramétrages de l'environnement des utilisateurs devraient être dans ce fichier.  Cela peut ressembler à ça<indexterm><primary>/etc/profile</primary><secondary>example</secondary></indexterm>&nbsp;:</para>
<screen>
# /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 &gt; /dev/null 2&gt;&amp;1

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

HOSTNAME=`/bin/hostname`
HISTSIZE=1000

# Clavier, sonnerie, style d'affichage&nbsp;: le fichier de configuration readline&nbsp;:
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
</screen>
<para>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 <xref linkend="sect_03_02" />.</para>
<para>Voir <xref linkend="chap_07" /> pour en savoir plus sur les structures <command>if</command> employées dans ce fichier&nbsp;; <xref linkend="chap_09" /> traite des boucles tel que <command>for</command>.</para>
<para>Le source Bash contient des exemples de fichiers <filename>profile</filename> 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.</para>
</sect3>
<sect3 id="sect_03_01_01_02"><title>/etc/bashrc</title>
<para>Sur des systèmes qui offrent divers types de Shell, il peut être judicieux de mettre la configuration spécifique à Bash dans ce fichier<indexterm><primary>configuration files</primary><secondary>/etc/bashrc</secondary></indexterm>, parce que <filename>/etc/profile</filename> est aussi lu par d'autres Shell, comme Bourne.  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. Dans un tel cas, le fichier de l'utilisateur <filename>~/.bashrc</filename> devrait pointer sur  <filename>/etc/bashrc</filename> afin de l'inclure dans le processus d'initialisation du Shell à la connexion.</para>
<para>Vous pouvez voir aussi que <filename>/etc/profile</filename> sur votre système contient seulement l'environnement Shell et le paramètrage du programme de démarrage, tandis que <filename>/etc/bashrc</filename> contient des définitions pour des fonctions Shell et des alias qui s'appliquent à tout le système <indexterm><primary>aliases</primary><secondary>examples</secondary></indexterm>.  Le fichier <filename>/etc/bashrc</filename> peut être appelé dans <filename>/etc/profile</filename> ou dans les fichiers d'initialisation Shell de chaque utilisateur.</para>
<para>Le source contient des exemples de fichiers <filename>bashrc</filename>, ou vous pouvez en trouver une copie dans <filename>/usr/share/doc/bash-2.05b/startup-files</filename>.   Ceci fait partie de <filename>bashrc</filename> et vient avec la documentation Bash<indexterm><primary>/etc/bashrc</primary><secondary>example</secondary></indexterm>&nbsp;:</para>  
<screen>
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."
}

</screen>
<para>A part les alias généraux, il contient des alias pratiques qui rendent correctes des commandes même mal libellées<indexterm><primary>aliases</primary><secondary>misspelled commands</secondary></indexterm>. Nous traiterons des alias à la <xref linkend="sect_03_05_02" />.  Ce fichier contient une fonction <command>pskill</command>, qui sera étudiée en détail au  <xref linkend="chap_11" />.</para>
</sect3>
</sect2>

<sect2 id="sect_03_01_02"><title>Les fichiers de configuration utilisateur</title>
<note><title>Je n'ai pas ces fichiers&nbsp;?&nbsp;!</title><para>Ces fichiers peuvent être absent de votre répertoire racine&nbsp;; créer les au besoin.</para></note>
<sect3 id="sect_03_01_02_01"><title>~/.bash_profile</title>
<para>C'est le fichier de configuration principal pour définir l'environnement personnel<indexterm><primary>configuration files</primary><secondary>.bash_profile</secondary></indexterm>.  Dans ce fichier l'utilisateur peut ajouter des options de configuration supplémentaires ou changer le paramétrage par défaut&nbsp;:</para>
<screen>
<prompt>franky~&gt;</prompt> <command>cat <filename>.bash_profile<indexterm><primary>.bash_profile</primary><secondary>example</secondary></indexterm></filename></command>
#################################################################
#                                                               #
#   .bash_profile file                                          #
#                                                               #
#   Exécuté 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
</screen>
<para>Cet utilisateur configure le caractère retour arrière selon le système d'exploitation sur lequel il se connecte. A part ça, <filename>.bashrc</filename> et <filename>.bash_login</filename> sont lus.</para>
</sect3>
<sect3 id="sect_03_01_02_02"><title>~/.bash_login</title>
<para>Ce fichier<indexterm><primary>configuration files</primary><secondary>.bash_login</secondary></indexterm> 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 <command>umask</command> et pour afficher une liste des utilisateurs connectés.  Cet utilisateur obtient aussi le calendrier du mois<indexterm><primary>.bash_login</primary><secondary>example</secondary></indexterm>&nbsp;:</para>
<screen>
#######################################################################
#                                                                     #
#   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"`
</screen>
<para>En l'absence de <filename>~/.bash_profile</filename>, ce fichier sera lu.</para>
</sect3>
<sect3 id="sect_03_01_02_03"><title>~/.profile</title>
<para>En l'absence<indexterm><primary>configuration files</primary><secondary>.profile</secondary></indexterm> de <filename>~/.bash_profile</filename> et <filename>~/.bash_login</filename>, <filename>~/.profile</filename> 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.</para>
</sect3>
<sect3 id="sect_03_01_02_04"><title>~/.bashrc</title>
<para>Aujourd'hui il est plus courant<indexterm><primary>configuration files</primary><secondary>.bashrc</secondary></indexterm> 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&nbsp;:  pas d'authentification.  Bash cherche <filename>~/.bashrc</filename> 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.</para>
<para>Dans ce fichier utilisateur, <filename>.bashrc</filename>, un ensemble de variables pour des programmes spécifiques et d'alias<indexterm><primary>aliases</primary><secondary>examples</secondary></indexterm> est défini après que le fichier à usage global <filename>/etc/bashrc</filename> ait été lu<indexterm><primary>.bashrc</primary><secondary>example</secondary></indexterm>&nbsp;:</para>
<screen>
<prompt>franky ~&gt;</prompt> <command>cat <filename>.bashrc</filename></command>
# /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 &amp;'

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

# La fin
<prompt>franky ~&gt;</prompt>
</screen> 
<para>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.</para>
<para>Les alias sont traités à la <xref linkend="sect_03_05" />.</para>
</sect3>
<sect3 id="sect_03_01_02_05"><title>~/.bash_logout</title>
<para>Ce fichier contient des instructions spécifiques pour la procédure de  déconnexion<indexterm><primary>configuration files</primary><secondary>.bash_logout</secondary></indexterm>.  Dans cet exemple<indexterm><primary>.bash_logout</primary><secondary>example</secondary></indexterm>, 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.</para>
<screen>
<prompt>franky ~&gt;</prompt> <command>cat <filename>.bash_logout</filename></command>
#######################################################################
#                                                                     #
#   Bash_logout file                                                  #
#                                                                     #
#  instructions exécutées par le Shell Bash à la déconnexion            #
#                                                                     #
#######################################################################
clear
<prompt>franky ~&gt;</prompt>
</screen>
</sect3>
</sect2>
<sect2 id="sect_03_01_03"><title>Modification des fichiers de configuration du Shell</title>
<para>Quand vous modifiez<indexterm><primary>configuration files</primary><secondary>change shell configuration</secondary></indexterm> n'importe lequel des fichiers ci-dessus, les utilisateurs doivent soit se reconnecter, soit exécuter (<command>source</command>) le fichier modifié afin que prennent effet les modifications.  De la deuxième manière, les modifications<indexterm><primary>configuration files</primary><secondary>prompt</secondary></indexterm> sont appliquées à la session active du Shell&nbsp;:</para>
<figure><title>Différentes invites pour des utilisateurs différents </title>
<mediaobject>
<imageobject>
<imagedata fileref="&images;prompt.eps" format="EPS"></imagedata>
</imageobject>
<imageobject>
<imagedata fileref="&images;prompt.png" format="PNG"></imagedata>
</imageobject>
<textobject>
<phrase>L'invite 1 est <quote>franky ~&gt;</quote>&nbsp;; l'invite est 
alors changée par 

<quote>export PS1="\[\033[1;42m\]$USER is in \w\[\033[0m\]"</quote> 

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 
<quote>root</quote> est défini de la même manière par définition de PS1 
en inverse vidéo rouge brillant.</phrase>

</textobject>
</mediaobject>
</figure>
<para>La plupart des scripts Shell s'exécutent dans leur propre environnement&nbsp;: les processus enfants n'héritent pas des variables du parent à moins que celui-ci les exporte. Exécuter avec <command>source</command> 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.</para>
<para>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.</para>
<para>Notez que <command>source <filename>resourcefile</filename></command> est équivalent à <command>. <filename>resourcefile</filename></command>.</para>
<para>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 <command>echo</command>, tout comme pour debugger un script&nbsp;; voir la <xref linkend="sect_02_03_02" />.  Vous pouvez ajouter des lignes comme celles-ci&nbsp;:</para>
<screen>
echo "Avant exécution de .bash_profile.."
</screen> 
<para>ou comme celles-ci&nbsp;:</para>
<screen>
echo "Avant définition de PS1 dans .bashrc:"
export PS1="[la bonne valeur]"
echo "PS1 est défini comme ceci $PS1"
</screen>
</sect2>

</sect1> 

<sect1 id="sect_03_02"><title>Variables</title>
<sect2 id="sect_03_02_01"><title>Types de variables</title>
<para>Comme dans l'exemple ci-dessus, les variables Shell<indexterm><primary>variables</primary><secondary>types</secondary></indexterm> sont en majuscule par convention.  Bash garde une liste de 2 types de variables&nbsp;:</para>
<sect3 id="sect_03_02_01_01"><title>Les variables Globales</title>
<para>Les variables Globales<indexterm><primary>variables</primary><secondary>global variables</secondary></indexterm>  ou variables d'environnement<indexterm><primary>variables</primary><secondary>environment variables</secondary></indexterm> sont disponibles dans tous les Shells.  Les commandes <command>env<indexterm><primary>commands</primary><secondary>env</secondary></indexterm></command> ou <command>printenv<indexterm><primary>commands</primary><secondary>printenv</secondary></indexterm></command> peuvent être employées pour afficher les variables d'environnement.  Ces programmes font partie du paquetage <emphasis>sh-utils</emphasis><indexterm><primary>commands</primary><secondary>sh-utils package</secondary></indexterm>.</para>
<para>Ci-dessous un affichage fréquent<indexterm><primary>printenv</primary><secondary>example</secondary></indexterm>&nbsp;:</para>
<screen>
<prompt>franky ~&gt;</prompt> <command>printenv</command>
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&gt;
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
</screen>
</sect3>
<sect3 id="sect_03_02_01_02"><title>Variables locales</title>
<para>Les variables locales<indexterm><primary>varibles</primary><secondary>local variables</secondary></indexterm> ne sont visibles que dans le Shell courant.  La commande intégrée <command>set</command> 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.</para>
<para>Ci-dessous un fichier diff obtenu par comparaison entre l'affichage de  <command>printenv</command> et de <command>set</command>, après l'avoir expurgé des fonctions qui sont aussi affichées par  <command>set</command>:</para>
<screen>
<prompt>franky ~&gt;</prompt> <command>diff <filename>set.sorted</filename> <filename>printenv.sorted</filename></command> | <command>grep <parameter>"&lt;"</parameter></command> | <command>awk <parameter>'{ print $2 }'</parameter></command>
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
</screen>
<note><title>Awk</title><para>L'outil GNU Awk est expliqué au <xref linkend="chap_06" />.</para></note>
</sect3>
<sect3 id="sect_03_02_01_03"><title>Variables typées selon leur contenu</title>
<para>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 se distinguent en 4 types<indexterm><primary>variables</primary><secondary>content types</secondary></indexterm>&nbsp;:</para>

<itemizedlist>
<listitem><para>Variables de chaîne de caractères (NdT&nbsp;: nous 
dirons simplement <quote>chaîne</quote> par la suite)</para></listitem>
<listitem><para>Variables d'entier</para></listitem>
<listitem><para>Variables de constantes</para></listitem>
<listitem><para>Variables tableau</para></listitem>
</itemizedlist>
<para>Nous traiterons ces types au <xref linkend="chap_10" />.  Dans l'immédiat, nous allons travailler avec des valeurs de variables de type chaîne et entier.</para>
</sect3>
</sect2>
<sect2 id="sect_03_02_02"><title>Créer des variables</title>
<para>Les variables<indexterm><primary>variables</primary><secondary>creation</secondary></indexterm> sont sensibles à la casse et en majuscule par défaut.  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&nbsp;:</para>
<screen>
<prompt>prompt&gt;</prompt> <command>export <varname>1number</varname>=<parameter>1</parameter></command>
bash: export: `1number=1': not a valid identifier
</screen>
<para>Pour affecter une valeur dans un Shell, la commande est</para>
<cmdsynopsis><command><varname>VARNAME</varname>="value"</command></cmdsynopsis>
<para>Laisser des espaces autour du signe égal causera une erreur. Il est conseillé d'entourer la valeur avec des guillemets lors de l'assignation&nbsp;: ça réduit les risques d'erreurs.</para>
<para>Divers exemples avec minuscules et majuscules, chiffres et espaces&nbsp;:</para>
<screen>
<prompt>franky ~&gt;</prompt> <command><varname>MYVAR1</varname>=<parameter>"2"</parameter></command>

<prompt>franky ~&gt;</prompt> <command>echo <varname>$MYVAR1</varname></command>
2

<prompt>franky ~&gt;</prompt> <command><varname>first_name</varname>=<parameter>"Franky"</parameter></command>

<prompt>franky ~&gt;</prompt> <command>echo <varname>$first_name</varname></command>
Franky

<prompt>franky ~&gt;</prompt> <command><varname>full_name</varname>=<parameter>"Franky M. Singh"</parameter></command>

<prompt>franky ~&gt;</prompt> <command>echo <varname>$full_name</varname></command>
Franky M. Singh

<prompt>franky ~&gt;</prompt> <command><varname>MYVAR-2</varname>=<parameter>"2"</parameter></command>
bash: MYVAR-2=2: command not found

<prompt>franky ~&gt;</prompt> <command><varname>MYVAR1</varname> =<parameter>"2"</parameter></command>
bash: MYVAR1: command not found

<prompt>franky ~&gt;</prompt> <command><varname>MYVAR1</varname>= <parameter>"2"</parameter></command>
bash: 2: command not found

<prompt>franky ~&gt;</prompt> <command>unset <varname>MYVAR1</varname> <varname>first_name</varname> <varname>full_name</varname></command>

<prompt>franky ~&gt;</prompt> <command>echo <varname>$MYVAR1</varname> <varname>$first_name</varname> <varname>$full_name</varname></command>
&lt;--no output--&gt;

<prompt>franky ~&gt;</prompt>
</screen>


</sect2>

<sect2 id="sect_03_02_03"><title>Exporter les variables</title>
<para>Une variable<indexterm><primary>variables</primary><secondary>exporting</secondary></indexterm> 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 <emphasis>export</emphasis> avec l'intégrée <command>export<indexterm><primary>built-ins</primary><secondary>export</secondary></indexterm></command>.  Les variables exportées sont appelées les variables d'environnement.  Définir et exporter sont souvent 2 actions faites en même temps.</para>
<cmdsynopsis><command>export <varname>VARNAME</varname>="<parameter>valeur</parameter>"</command></cmdsynopsis>
<para>Un sous-Shell<indexterm><primary>variables</primary><secondary>subshells</secondary></indexterm>  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&nbsp;:</para>
<screen>
<prompt>franky ~&gt;</prompt> <command><varname>full_name</varname>=<parameter>"Franky M. Singh"</parameter></command>

<prompt>franky ~&gt;</prompt> <command>bash</command>

<prompt>franky ~&gt;</prompt> <command>echo <varname>$full_name</varname></command>


<prompt>franky ~&gt;</prompt> <command>exit</command>

<prompt>franky ~&gt;</prompt> <command>export <varname>full_name</varname></command>

<prompt>franky ~&gt;</prompt> <command>bash</command>

<prompt>franky ~&gt;</prompt> <command>echo <varname>$full_name</varname></command>
Franky M. Singh

<prompt>franky ~&gt;</prompt> <command>export <varname>full_name</varname>=<parameter>"Charles the Great"</parameter></command>

<prompt>franky ~&gt;</prompt> <command>echo <varname>$full_name</varname></command>
Charles the Great

<prompt>franky ~&gt;</prompt> <command>exit</command>

<prompt>franky ~&gt;</prompt> <command>echo <varname>$full_name</varname></command>
Franky M. Singh

<prompt>franky ~&gt;</prompt>
</screen>
<para>Quand d'abord on essaye de lire la valeur de <varname>full_name</varname> dans un sous-Shell, on n'a rien (<command>echo</command> affiche une chaîne nulle).  Le sous-Shell finit, et <varname>full_name</varname> 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.</para>
</sect2>

<sect2 id="sect_03_02_04"><title>Variables réservées</title>
<sect3 id="sect_03_02_04_01"><title>Variables réservées du Bourne Shell</title>
<para>Bash utilise certaines variables Shell <indexterm><primary>variables</primary><secondary>Bourne shell reserved</secondary></indexterm> 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&nbsp;:</para>
<table id="table_03_01" frame="all"><title>Variables réservées Bourne Shell</title>
<tgroup cols="2" align="left" colsep="1" rowsep="1">
<thead>
<row><entry>Nom de variable</entry><entry>Définition</entry></row>
</thead>
<tbody>
<row><entry>CDPATH</entry><entry>Une liste des répertoires, séparés par deux points(&nbsp;:), utilisés comme chemin de recherche pour l'intégrée <command>cd</command>.</entry></row>
<row><entry>HOME</entry><entry>Le répertoire racine de l'utilisateur actif&nbsp;; le chemin par défaut pour l'intégrée <command>cd</command>.  La valeur de cette variable est aussi utilisée par l'expansion du tilde</entry></row>
<row><entry>IFS</entry><entry>Une liste de caractères qui peuvent séparer les champs&nbsp;; utilisé par Shell pour découper les mots lors du processus d'expansion.</entry></row>
<row><entry>MAIL</entry><entry>Si à ce paramètre est affecté un nom de fichier et que la variable <varname>MAILPATH</varname> n'est pas définie, Bash informe l'usager de l'arrivée d'un mail dans le fichier spécifié.</entry></row>
<row><entry>MAILPATH</entry><entry>Une liste de fichiers, séparés par deux points (:), dont se sert le Shell régulièrement pour rechercher les nouveaux mails. </entry></row>
<row><entry>OPTARG</entry><entry>La valeur de l'argument de la dernière option traitée par l'intégrée <command>getopts</command>.</entry></row>
<row><entry>OPTIND</entry><entry>Le rang de l'argument de la dernière option traitée par l'intégré <command>getopts</command>.</entry></row>
<row><entry>PATH</entry><entry>Une liste de répertoires, séparés par deux points(&nbsp;:), dans lesquels le Shell recherche les commandes.</entry></row>
<row><entry>PS1</entry><entry>La principale chaîne d'invite.  La valeur par défaut est <quote>'\s-\v\$ '</quote>.  </entry></row>
<row><entry>PS2</entry><entry>La chaîne alternative d'invite.  La valeur par défaut est <quote>'&gt; '</quote>.</entry></row>
</tbody>
</tgroup>
</table>

</sect3>
<sect3 id="sect_03_02_04_02"><title>Les variables réservées de Bash</title>
<para>Ces variables sont définies ou utilisées par Bash<indexterm><primary>variables</primary><secondary>Bash reserved</secondary></indexterm>, mais les autres Shells normalement ne les traitent pas spécialement.</para>
<table id="table_03_02" frame="all"><title>Les variables réservées de Bash</title>
<tgroup cols="2" align="left" colsep="1" rowsep="1">
<thead>
<row><entry>Nom de variable</entry><entry>Définition</entry></row>
</thead>
<tbody>
<row><entry>auto_resume</entry><entry>Cette 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.</entry></row>
<row><entry>BASH</entry><entry>Le chemin complet où se trouve l'exécutable du Bash actif.</entry></row>
<row><entry>BASH_ENV</entry><entry>Si 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.</entry></row>
<row><entry>BASH_VERSION</entry><entry>Le numéro de version du Bash actif.</entry></row>
<row><entry>BASH_VERSINFO</entry><entry>Un tableau en lecture dont chaque élément mémorise un niveau de la version du Bash actif.</entry></row>
<row><entry>COLUMNS</entry><entry>Utilisé par l'intégrée <command>select</command> 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 <emphasis>SIGWINCH</emphasis>.</entry></row>
<row><entry>COMP_CWORD</entry><entry>Un index dans <varname>${COMP_WORDS}</varname> qui pointe sur le mot où se trouve le curseur.</entry></row>
<row><entry>COMP_LINE</entry><entry>La ligne de commande courante.</entry></row>
<row><entry>COMP_POINT</entry><entry>Index qui point la position du curseur dans la commande courante.</entry></row>
<row><entry>COMP_WORDS</entry><entry>Une variable tableau dont chaque élément renvoie un mot de la commande courante.</entry></row>
<row><entry>COMPREPLY</entry><entry>Une 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.</entry></row>
<row><entry>DIRSTACK</entry><entry>Une variable tableau mémorisant le contenu de la pile de répertoires.</entry></row>
<row><entry>EUID</entry><entry>Le nombre identifiant l'utilisateur actif.</entry></row>
<row><entry>FCEDIT</entry><entry>L'éditeur utilisé par défaut par l'option <option>-e</option> de l'intégrée <command>fc</command>.</entry></row>
<row><entry>FIGNORE</entry><entry>Une liste de suffixes à ignorer, séparés par deux points (&nbsp;:), quand se produit la génération de noms de fichiers.</entry></row>
<row><entry>FUNCNAME</entry><entry>Contient le nom de fonction si une fonction Shell est en train de s'exécuter.</entry></row>
<row><entry>GLOBIGNORE</entry><entry>Une liste de patrons, séparés par deux points (&nbsp;:), qui sert à définir les fichiers à ignorer lors de la génération de nom de fichiers.</entry></row>
<row><entry>GROUPS</entry><entry>Un tableau qui mémorise les groupes auxquels l'utilisateur appartient.</entry></row>
<row><entry>histchars</entry><entry>Jusqu'à 3 caractères permettant de contrôler l'expansion d'historique, la substitution rapide, et le découpage en <emphasis>mots</emphasis>.</entry></row>
<row><entry>HISTCMD</entry><entry>Le  numéro d'historique, ou le rang dans la liste d'historique de la commande en cours.</entry></row>
<row><entry>HISTCONTROL</entry><entry>Détermine si la commande en cours est ajoutée au fichier d'historique.</entry></row>
<row><entry>HISTFILE</entry><entry>Le nom de fichier dans lequel l'historique des commandes est conservé.  La valeur par défaut est <filename>~/.bash_history</filename>.</entry></row>
<row><entry>HISTFILESIZE</entry><entry>Détermine le nombre maximum de lignes que mémorise le fichier d'historique&nbsp;; par défaut 500.</entry></row>
<row><entry>HISTIGNORE</entry><entry>Une liste de patrons, séparés par deux points (&nbsp;:), qui sert à déterminer quelles commandes sont mémorisées dans l'historique.</entry></row>
<row><entry>HISTSIZE</entry><entry>Détermine le nombre maximum de commandes que mémorise le fichier d'historique&nbsp;; par défaut 500.</entry></row>
<row><entry>HOSTFILE</entry><entry>Contient le nom d'un fichier au format de <filename>/etc/hosts</filename> qui devrait être lu quand le Shell a besoin du nom de machine hôte.</entry></row>
<row><entry>HOSTNAME</entry><entry>Délivre le nom de la machine hôte.</entry></row>
<row><entry>HOSTTYPE</entry><entry>Une chaîne qui décrit la machine sur laquelle Bash est en train de tourner.</entry></row>
<row><entry>IGNOREEOF</entry><entry>Détermine l'action du Shell quand il reçoit le caractère <emphasis>EOF</emphasis> et uniquement celui-là.</entry></row>
<row><entry>INPUTRC</entry><entry>Délivre le nom du fichier d'initialisation de Readline, se substituant à <filename>/etc/inputrc</filename>.</entry></row>
<row><entry>LANG</entry><entry>Utilisé pour tenter de déterminer le particularisme local lorsque qu'aucune  variable commençant par <varname>LC_</varname> ne spécifie la catégorie.</entry></row>
<row><entry>LC_ALL</entry><entry>Cette variable se substitue à <varname>LANG</varname> et à toute autre variable  <varname>LC_</varname> en spécifiant une catégorie de particularisme local.</entry></row>
<row><entry>LC_COLLATE</entry><entry>Cette 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.</entry></row>
<row><entry>LC_CTYPE</entry><entry>Cette variable détermine l'interprétation des caractères et le comportement des  classes de caractères [NdT&nbsp;: ex&nbsp;: [&nbsp;:alpha] ] lors de l'expansion des noms de fichiers et de la recherche de patrons.</entry></row>
<row><entry>LC_MESSAGES</entry><entry>Cette variable détermine le particularisme utilisé pour traduire les chaînes entre guillemets précédés par un <quote>$</quote>.</entry></row>
<row><entry>LC_NUMERIC</entry><entry>Cette variable détermine la catégorie des particularismes employés pour formater les nombres.</entry></row>
<row><entry>LINENO</entry><entry>Le numéro de la ligne en train d'être traitée dans le script ou la fonction Shell.</entry></row>
<row><entry>LINES</entry><entry>Utilisé par l'intégrée <command>select</command> pour déterminer la longueur de colonne lors de l'affichage de listes de sélection.</entry></row>
<row><entry>MACHTYPE</entry><entry>Une chaîne qui décrit complètement le type de système sur lequel Bash tourne, dans le format standard GNU CPU-COMPANY-SYSTEM.</entry></row>
<row><entry>MAILCHECK</entry><entry>Intervalle de temps (en secondes) entre 2 vérifications de présence de mail dans le fichier spécifié par <varname>MAILPATH</varname> ou <varname>MAIL</varname>.</entry></row>
<row><entry>OLDPWD</entry><entry>Contient le nom du répertoire précédent accédé par l'intégrée <command>cd</command>.</entry></row>
<row><entry>OPTERR</entry><entry>Si défini à 1, Bash affiche les messages d'erreur générés par l'intégrée  <command>getopts</command>.</entry></row>
<row><entry>OSTYPE</entry><entry>Une chaîne décrivant le système d'exploitation sur lequel Bash tourne.</entry></row>
<row><entry>PIPESTATUS</entry><entry>Un 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).</entry></row>
<row><entry>POSIXLY_CORRECT</entry><entry>Si cette variable est définie quand <command>bash</command> démarre, le Shell entre en mode  POSIX.</entry></row>
<row><entry>PPID</entry><entry>L'identifiant du process parent du Shell.</entry></row>
<row><entry>PROMPT_COMMAND</entry><entry>Définie, la valeur est interprétée comme une commande à exécuter avant l'affichage de chaque invite (<varname>PS1</varname>).</entry></row>
<row><entry>PS3</entry><entry>La valeur de cette variable est utilisée comme l'invite pour la commande <command>select</command>.  Par défaut <quote>'#? '</quote></entry></row>
<row><entry>PS4</entry><entry>La valeur est l'invite affichée avant que la commande soit affichée en echo quand l'option <option>-x</option> est activée&nbsp;; par defaut <quote>'+ '</quote>.</entry></row>
<row><entry>PWD</entry><entry>Renvoie le nom de répertoire courant défini par l'intégrée <command>cd</command>.</entry></row>
<row><entry>RANDOM</entry><entry>Chaque 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.</entry></row>
<row><entry>REPLY</entry><entry>Paramètre par défaut de l'intégrée <command>read</command>.</entry></row>
<row><entry>SECONDS</entry><entry>Renvoie le nombre de secondes écoulées depuis que le Shell est lancé.</entry></row>
<row><entry>SHELLOPTS</entry><entry>Une liste des options Shell activées, séparées par deux points(&nbsp;:).</entry></row>
<row><entry>SHLVL</entry><entry>Valeur augmentée de 1 chaque fois qu'une nouvelle instance de Bash est lancée.</entry></row>
<row><entry>TIMEFORMAT</entry><entry>Cette 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é <command>time</command> est spécifié.</entry></row>
<row><entry>TMOUT</entry><entry>Défini à une valeur supérieure à zéro, <varname>TMOUT</varname> est considéré comme le temps imparti maximum à l'intégrée <command>read</command>.  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.</entry></row>
<row><entry>UID</entry><entry>Le nombre, le véritable identifiant, de l'usagé actif.</entry></row>
</tbody>
</tgroup>
</table>
<para>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.</para>

</sect3>



</sect2>
<sect2 id="sect_03_02_05"><title>Paramètres spéciaux</title>
<para>Le Shell considère certains paramètres <indexterm><primary>variables</primary><secondary>special parameters</secondary></indexterm> spécifiquement.  Ces paramètres ne peuvent qu'être référencés&nbsp;; leur affectation n'est pas permise.</para>
<table id="table_03_03" frame="all"><title>Les variables Bash spéciales</title>
<tgroup cols="2" align="left" colsep="1" rowsep="1">
<thead>
<row><entry>Nom</entry><entry>Définition</entry></row>
</thead>
<tbody>
<row><entry><varname>$*</varname></entry><entry>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 <varname>IFS</varname>.</entry></row>
<row><entry><varname>$@</varname></entry><entry>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.</entry></row>
<row><entry><varname>$#</varname></entry><entry>Renvoie le nombre de paramètres positionnels en décimal.</entry></row>
<row><entry><varname>$?</varname></entry><entry>Renvoie le statut d'exécution de l'instruction la plus récemment exécutée en avant-plan dans un tube.</entry></row>
<row><entry><varname>$-</varname></entry><entry>Renvoie les options déclarées lors de l'invocation de l'intégrée <command>set</command>, ou celles positionnées par le Shell lui-même (tel que <option>-i</option>).</entry></row>
<row><entry><varname>$$</varname></entry><entry>Renvoie l'identifiant du process du Shell.</entry></row>
<row><entry><varname>$!</varname></entry><entry>Renvoie l'identifiant du process de la commande la plus récemment exécutée en tâche de fond (asynchrone).</entry></row>
<row><entry><varname>$0</varname></entry><entry>Renvoie le nom du Shell ou du script Shell actif.</entry></row>
<row><entry><varname>$_</varname></entry><entry>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.
</entry></row>
</tbody>
</tgroup>
</table>
<note><title>$* versus $@</title>
<para>L'implémentation de <quote>$*</quote> a toujours été un problème et aurait dû être remplacé pratiquement par le comportement de  <quote>$@</quote>.  Dans presque tous les cas quand le programmeur utilise  <quote>$*</quote>, il veut dire <quote>$@</quote>.  <quote>$*</quote> peut être la cause de bugs et même de trou de sécurité dans votre programme.</para> 
</note>
<para>Les paramètres positionnels<indexterm><primary>variables</primary><secondary>positional parameters</secondary></indexterm> sont les mots qui suivent le nom d'un script Shell.  Ils définissent les variables <varname>$1</varname>, <varname>$2</varname>, <varname>$3</varname> etc.  Autant que nécessaire, ces variables sont ajoutées dans un tableau interne.  <varname>$#</varname> mémorise le nombre de paramètres, comme démontré dans ce simple<indexterm><primary>positional parameters</primary><secondary>example</secondary></indexterm> script&nbsp;:</para>
<screen>
#!/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 $#."
</screen>
<para>A l'exécution on peut donner autant de paramètres que l'on veut<indexterm><primary>arguments</primary><secondary>positional parameters</secondary></indexterm>&nbsp;:</para>
<screen>
<prompt>franky ~&gt;</prompt> <command>positional.sh <parameter>un deux trois quatre cinq</parameter></command>
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.

<prompt>franky ~&gt;</prompt> <command>positional.sh <parameter>un deux</parameter></command>
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
</screen>
<para>Plus de précisions sur l'évaluation de ces paramètres au <xref linkend="chap_07" /> et à la <xref linkend="sect_09_07" />.</para>
<para>Quelques exemples sur les autres paramètres spéciaux<indexterm><primary>special parameters</primary><secondary>examples</secondary></indexterm>&nbsp;:</para>
<screen>
<prompt>franky ~&gt;</prompt> <command>grep <parameter>dictionary</parameter> <filename>/usr/share/dict/words</filename></command>
dictionary

<prompt>franky ~&gt;</prompt> <command>echo <varname>$_</varname></command>
/usr/share/dict/words

<prompt>franky ~&gt;</prompt> <command>echo <varname>$$</varname></command>
10662

<prompt>franky ~&gt;</prompt> <command>mozilla &amp;</command>
[1] 11064

<prompt>franky ~&gt;</prompt> <command>echo <varname>$!</varname></command>
11064

<prompt>franky ~&gt;</prompt> <command>echo <varname>$0</varname></command>
bash

<prompt>franky ~&gt;</prompt> <command>echo <varname>$?</varname></command>
0

<prompt>franky ~&gt;</prompt> <command>ls <filename>doesnotexist</filename></command>
ls: doesnotexist: No such file or directory

<prompt>franky ~&gt;</prompt> <command>echo <varname>$?</varname></command>
1

<prompt>franky ~&gt;</prompt>
</screen>
<para>L'utilisateur <emphasis>franky</emphasis> lance la commande <command>grep</command>, qui a pour effet la valorisation de la variable <varname>_</varname>. L'ID du processus de son Shell est 10662.  Après avoir mis un travail en tâche de fond, la variable <varname>!</varname> renvoie l'ID du processus du travail en tâche de fond.  Le Shell actif est <command>bash</command>.  Quand une erreur se produit, <varname>?</varname> renvoie un statut d'exécution différent de 0 (zéro).</para>
</sect2>
<sect2 id="sect_03_02_06"><title>Script à finalités multiples grâce aux variables</title>
<para>En plus<indexterm><primary>variables</primary><secondary>advantages</secondary></indexterm> 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 <emphasis>franky</emphasis> vers un serveur distant&nbsp;:</para>
<screen>
#!/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 &gt; /dev/null 2&gt;&amp;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&gt; /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 &gt; /dev/null 2&gt;&amp;1

# Crée un marqueur temporel dans un fichier journal..
date &gt; /home/franky/log/home_backup.log
echo backup succeeded &gt; /home/franky/log/home_backup.log
</screen>
<para> 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 <emphasis>franky</emphasis> veuille donner ce script à <emphasis>carol</emphasis>, alors carol aura à faire des modifications par l'éditeur avant de pouvoir sauvegarder son répertoire.  De même si <emphasis>franky</emphasis> 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&nbsp;:</para>
<screen>
#!/bin/bash
                                                                                                 
# Ce script fait une sauvegarde de mon répertoire racine.

# Modifier les valeurs des variables pour que le script tourne pour vous&nbsp;:
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 &gt; /dev/null 2&gt;&amp;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&gt; /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 &gt; /dev/null 2&gt;&amp;1

# Crée un marqueur temporel dans un fichier journal..
date &gt; $LOGFILE
echo backup succeeded &gt; $LOGFILE
</screen>

<note><title>Répertoires volumineux et faible bande passante</title>
<para>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 <command>rsync</command> pour garder les répertoires synchronisés entre les 2 machines.</para>
</note>
</sect2>

</sect1>

<sect1 id="sect_03_03"><title>Echappement et protection de caractères</title>
<sect2 id="sect_03_03_01"><title>Pourquoi protéger ou 'échapper' un caractère&nbsp;?</title>
<para>Certaines touches(NdT&nbsp;: séquence de caractères) 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&nbsp;: 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.</para>
</sect2>
<sect2 id="sect_03_03_02"><title>Le caractère Echap (escape)</title>
<para>Le caractère Echap<indexterm><primary>quoting characters</primary><secondary>escape characters</secondary></indexterm>  sert à inhiber 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 <emphasis>saut de ligne</emphasis>.  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&nbsp;; le slash inversé est ôté du flot entré et donc en fait ignoré.</para>
<screen>
<prompt>franky ~&gt;</prompt> <command><varname>date</varname>=<parameter>20021226</parameter></command>

<prompt>franky ~&gt;</prompt> <command>echo <varname>$date</varname></command>
20021226

<prompt>franky ~&gt;</prompt> <command>echo <parameter>\$date</parameter></command>
$date
</screen>
<para>Dans cet exemple, la variable <varname>date</varname> est définie avec une valeur.  Le premier <command>echo</command> affiche la valeur de la variable, mais dans le second le signe $ est protégé.</para>
</sect2>
<sect2 id="sect_03_03_03"><title>Les apostrophes</title>
<para>Les<indexterm><primary>quoting characters</primary><secondary>single quotes</secondary></indexterm> 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.</para>
<para>Continuons avec l'exemple précédent&nbsp;:</para>
<screen>
<prompt>franky ~&gt;</prompt> <command>echo <parameter>'$date'</parameter></command>
$date
</screen>
</sect2>
<sect2 id="sect_03_03_04"><title>Les guillemets</title>
<para>Avec les<indexterm><primary>quoting characters</primary><secondary>double quotes</secondary></indexterm> 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é.</para>
<para>Le $ et `` conservent leur sens spécial à l'intérieur de guillemets.</para>
<para>Le slash inversé conserve son effet 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.</para>
<para>Un guillemet peut être protégé à l'intérieur de guillemets en le faisant précéder par \.</para>
<screen>
<prompt>franky ~&gt;</prompt> <command>echo <varname>"$date"</varname></command>
20021226

<prompt>franky ~&gt;</prompt> <command>echo <parameter>"`date`"</parameter></command>
Sun Apr 20 11:22:06 CEST 2003

<prompt>franky ~&gt;</prompt> <command>echo <parameter>"I'd say: \"Go for it!\""</parameter></command>
I'd say: "Go for it&nbsp;!"

<prompt>franky ~&gt;</prompt> <command>echo <parameter>"\"</parameter></command>
<prompt>More input&gt;</prompt><command>"</command>

<prompt>franky ~&gt;</prompt> <command>echo <parameter>"\\"</parameter></command>
\
</screen>

</sect2>
<sect2 id="sect_03_03_05"><title>Codage ANSI-C</title>
<para>Les mots<indexterm><primary>quoting characters</primary><secondary>ANSI-C quoting</secondary></indexterm> de la forme <quote>$'MOT'</quote> 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<indexterm><primary>ANSI-C</primary><secondary>quoting</secondary></indexterm>.  La séquence d'échappement du slash inversé peut être trouvée dans la documentation Bash.</para>
</sect2>
<sect2 id="sect_03_03_06"><title>Particularités</title>
<para>Une chaîne<indexterm><primary>quoting characters</primary><secondary>locale</secondary></indexterm>  entre guillemets précédée par un $ sera traitée selon la norme en vigueur.  Si cette norme est celle de <quote>C</quote> ou de <quote>POSIX</quote>, le $ est ignoré.  Si la chaîne est transposée avec remplacement, le résultat est entre guillemets.</para>

</sect2>

</sect1>

<sect1 id="sect_03_04"><title>Le processus d'expansion de Shell</title>
<sect2 id="sect_03_04_0"><title>Généralité</title>
<para>Après que la commande ait été décomposée en <emphasis>éléments</emphasis> (voir la <xref linkend="sect_01_04_01_01" />), 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.</para>
<para>Après toutes les sortes d'expansions effectuées, guillemets et apostrophes sont éliminés.</para>
</sect2>
<sect2 id="sect_03_04_01"><title>L'expansion d'accolades</title>
<para>L'expansion d'accolade<indexterm><primary>expansion</primary><secondary>brace expansion</secondary></indexterm> 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 <emphasis>préfixe</emphasis> 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 <emphasis>suffixe</emphasis> 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.</para>
<para>L'expansion d'accolades<indexterm><primary>brace expansion</primary><secondary>examples</secondary></indexterm> peut être imbriquée.  Le résultat des chaînes ainsi obtenues n'est pas trié&nbsp;; l'ordre de gauche à droite est préservé.</para>
<screen>
<prompt>franky ~&gt;</prompt> <command>echo <parameter>sp{el,il,al}l</parameter></command>
spell spill spall
</screen>
<para>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  <quote>${</quote> n'est pas éligible à l'expansion d'accolade.</para>
<para>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.</para>
</sect2>
<sect2 id="sect_03_04_02"><title>L'expansion du tilde</title>
<para>Si un mot commence par un tilde non protégé <indexterm><primary>expansion</primary><secondary>tilde expansion</secondary></indexterm> (<quote>~</quote>), 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 <emphasis>préfixe tilde</emphasis>.  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 <varname>HOME</varname>.  Si <varname>HOME</varname> 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é.</para>
<para> Si le préfixe tilde<indexterm><primary>tilde expansion</primary><secondary>syntax</secondary></indexterm> est <quote>~+</quote>, la valeur de la variable Shell <varname>PWD</varname> remplace le préfixe tilde.  Si le préfixe tilde est <quote>~-</quote>, la valeur de la variable Shell <varname>OLDPWD</varname>, si définie, s'y substitue.</para>
<para>Si les caractères suivant le tilde dans le préfixe consistent en un nombre N, optionnellement préfixé par <quote>+</quote> ou <quote>-</quote>, 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 <command>dirs</command> 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 <quote>+</quote> ou <quote>-</quote>, <quote>+</quote> est implicite.</para>
<para>Si le nom de connection est invalide, ou si l'expansion de tilde échoue, le mot est laissé tel quel.</para>
<para>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 <quote>:</quote> ou un <quote>=</quote>.  Dans ce cas l'expansion du tilde se produit.  Par conséquent, on peut utiliser un nom de fichier avec tilde dans <varname>PATH</varname>, <varname>MAILPATH</varname>, et <varname>CDPATH</varname>, et le Shell utilise l'expansion du nom.</para>
<para>Exemple&nbsp;:</para>
<screen>
<prompt>franky ~&gt;</prompt> <command>export <varname>PATH</varname>=<parameter>"$PATH:~/testdir"</parameter></command>
</screen>
<para><filename>~/testdir</filename> sera interprété en  <varname>$HOME</varname><filename>/testdir</filename>, donc si <varname>$HOME</varname> est <filename>/var/home/franky</filename>, le répertoire <filename>/var/home/franky/testdir</filename> sera ajouté au contenu de la variable <varname>PATH</varname>.</para>
</sect2>
<sect2 id="sect_03_04_03"><title>Paramètre Shell et expansion de variable</title>
<para>Le caractère <quote>$</quote><indexterm><primary>expansion</primary><secondary>variable expansion</secondary></indexterm> 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.</para>
<para>Quand l'accolade est utilisée, le premier <quote>}</quote> - 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.</para>
<para>La forme basique de l'expansion de paramètre est <quote>${PARAMETRE}</quote>.  La valeur de <quote>PARAMETRE</quote> y est substituée.  Les accolades sont requises quand <quote>PARAMETRE</quote> est un paramètre positionnel avec un symbole de plus de 1 caractère, ou quand <quote>PARAMETRE</quote> est suivi par un caractère qui ne doit pas être interprété comme faisant parti du symbole.</para>
<para>Si le premier caractère de <quote>PARAMETRE</quote> est un point d'exclamation, Bash considère les caractères suivants de <quote>PARAMETRE</quote> comme étant le symbole de la variable&nbsp;; cette variable est alors interprétée et utilisée dans la suite de la substitution, plutôt que la valeur de  <quote>PARAMETRE</quote> lui-même.  Ceci est connu sous le nom d'<emphasis>expansion indirecte</emphasis>.</para>
<para>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<indexterm><primary>variable and parameter expansion</primary><secondary>example</secondary></indexterm>&nbsp;:</para>
<screen>
<prompt>franky ~&gt;</prompt> <command>echo <varname>$SHELL</varname></command>
/bin/bash
</screen>

<para>Voici un exemple d'expansion indirecte<indexterm><primary>expansion</primary><secondary>indirect expansion</secondary></indexterm>&nbsp;:</para>
<screen>
<prompt>franky ~&gt;</prompt> <command>echo <varname>${!N*}</varname></command>
NNTPPORT NNTPSERVER NPX_PLUGIN_PATH
</screen>
<para>Notez que cela ne donne pas la même chose que <command>echo <varname>$N*</varname></command>.</para>
<para>La construction suivante permet la création du nom de variable si il n'existe pas&nbsp;:</para>
<cmdsynopsis><command>${<varname>VAR</varname>:=<parameter>value</parameter>}</command></cmdsynopsis>
<para>Exemple&nbsp;:</para>
<screen>
<prompt>franky ~&gt;</prompt> <command>echo <varname>$FRANKY</varname></command>

<prompt>franky ~&gt;</prompt> <command>echo <parameter>${FRANKY:=Franky}</parameter></command>
Franky
</screen>
<para>Cependant, les paramètres spéciaux, dont les paramètres positionnels, ne doivent pas être affectés par ce biais.</para>
<para>Nous approfondirons l'utilisation de l'accolade dans le traitement des variables au <xref linkend="chap_10" />.  Les pages info de Bash fournissent aussi d'autres informations.</para>

</sect2>
<sect2 id="sect_03_04_04"><title>La substitution de commande</title>
<para>La substitution de commande<indexterm><primary>expansion</primary><secondary>command substitution</secondary></indexterm> permet de remplacer la commande elle-même par son résultat.  La substitution de commande<indexterm><primary>command substitution</primary><secondary>syntax</secondary></indexterm> survient quand une commande est enchâssée ainsi&nbsp;:</para>
<cmdsynopsis><command>$(commande)</command></cmdsynopsis>
<para>ou ainsi avec les apostrophes inversées&nbsp;:</para>
<cmdsynopsis><command>`commande`</command></cmdsynopsis>
<para>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 ne sont pas éliminés, mais ils peuvent l'avoir été pendant le découpage en mot.</para>
<screen>
<prompt>franky ~&gt;</prompt> <command>echo <parameter>`date`</parameter></command>
Thu Feb 6 10:06:20 CET 2003
</screen>
<para>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 <quote>$</quote>, <quote>`</quote>, ou <quote>\</quote>.  La première apostrophe inversée non précédée d'un slash inversé termine la commande de substitution.  Quand la forme <quote>$(COMMANDE)</quote> est utilisée, tous les caractères entre parenthèses font partie de la commande&nbsp;; aucun n'est traité spécifiquement.</para>
<para>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.</para>
<para>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.</para>

</sect2>
<sect2 id="sect_03_04_05"><title>L'expansion arithmétique</title>
<para>L'expansion arithmétique<indexterm><primary>expansion</primary><secondary>arithmetic expansion</secondary></indexterm> permet l'évaluation d'une expression arithmétique<indexterm><primary>arithmetic expansion</primary><secondary>syntax</secondary></indexterm> et la substitution par le résultat.  Le format pour l'expansion arithmétique est&nbsp;:</para><cmdsynopsis><command>$(( EXPRESSION ))</command></cmdsynopsis>
<para>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.</para>
<para>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<indexterm><primary>arithmetic expansion</primary><secondary>operators</secondary></indexterm>, la liste ressemble à ceci&nbsp;:</para>
<table id="table_03_04" frame="all">
<title>Opérateurs arithmétiques</title>
<tgroup cols="2" align="left" colsep="1" rowsep="1">
<thead>
<row><entry>Opérateur</entry><entry>sens</entry></row>
</thead>
<tbody>
<row><entry>VAR++ et VAR--</entry><entry>variable: post-incrément et post-décrément</entry></row>
<row><entry>++VAR et --VAR</entry><entry>variable: pré-incrément et pré-décrément</entry></row>
<row><entry>- et +</entry><entry>moins et plus</entry></row>
<row><entry>! et ~ </entry><entry>négation logique et bit à bit</entry></row>
<row><entry>**</entry><entry>exponentiation</entry></row>
<row><entry>*, / et %</entry><entry>multiplication, division, reste</entry></row>
<row><entry>+ et -</entry><entry>addition, soustraction</entry></row>
<row><entry>&lt;&lt; and &gt;&gt;</entry><entry>Décalage des bits à gauche ou à droite</entry></row>
<row><entry>&lt;=, &gt;=, &lt; et &gt;</entry><entry>opérateurs de comparaison</entry></row>
<row><entry>== et !=</entry><entry>égalité et inégalité</entry></row>
<row><entry>&amp;</entry><entry>ET logique</entry></row>
<row><entry>^</entry><entry>OU logique exclusif</entry></row>
<row><entry>|</entry><entry>OU logique</entry></row>
<row><entry>&amp;&amp;</entry><entry>ET logique</entry></row>
<row><entry>||</entry><entry>OU logique</entry></row>
<row><entry>expr ? expr : expr</entry><entry>évaluation conditionnelle</entry></row>
<row><entry>=, *=, /=, %=, +=, -=, &lt;&lt;=, &gt;&gt;=, &amp;=, ^= et |=</entry><entry>affectations</entry></row>
<row><entry>,</entry><entry>séparateur entre expressions</entry></row>
</tbody>
</tgroup>
</table>
<para>Les variables Shell sont autorisées comme opérandes&nbsp;; l'expansion 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.</para>
<para>Une constante commençant par un 0 (zéro)  est considérée comme un chiffre octal.  Un <quote>0x</quote> ou <quote>0X</quote> au début marque l'hexadécimal.  Sinon, un nombre prend la forme <quote>[BASE'#']N</quote>, où  <quote>BASE</quote> est un nombre décimal entre 2 et 64 représentant la base arithmétique, et N un nombre dans cette base.  Si <quote>BASE'#'</quote> est omis, alors la base 10 est utilisée.  Les chiffres supérieurs à 9 sont représentés par les minuscules, les majuscules, <quote>@</quote>, et <quote>_</quote>, dans cet ordre.  Si <quote>BASE</quote> est inférieur ou égale à 36, les minuscules et les majuscules sont interchangeables dans leur représentation des chiffres entre 10 et 35.</para>
<para>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.</para>
<para>Autant que possible, les utilisateurs de Bash devraient essayer d'utiliser la syntaxe avec les crochets&nbsp;:</para>
<cmdsynopsis><command>$[ EXPRESSION ]</command></cmdsynopsis>
<para>Cependant, ceci ne fait qu'évaluer l'<emphasis>EXPRESSION</emphasis>, et ne teste pas&nbsp;:</para>
<screen>
<prompt>franky ~&gt;</prompt> <command>echo <parameter>$[365*24]</parameter></command>
8760
</screen>
<para>Voir <xref linkend="sect_07_01_02_02" />, entre autres, pour des exemples pratiques de scripts.</para>
</sect2>
<sect2 id="sect_03_04_06"><title>La substitution de processus</title>
<para>La substitution de processus<indexterm><primary>expansion</primary><secondary>process substitution</secondary></indexterm> est effectuée par les systèmes qui admettent les tubes (pipes) nommés (FIFO&nbsp;: NdT=First In First Out=premier entré, premier sorti) ou la méthode <filename>/dev/fd</filename> de nommage de fichiers ouverts.  Ca se présente sous la forme<indexterm><primary>process substitution</primary><secondary>syntax</secondary></indexterm> de</para>
<cmdsynopsis><command>&lt;(LIST)</command></cmdsynopsis>
<para>ou l'option</para>
<cmdsynopsis><command>&gt;(LIST)</command></cmdsynopsis>
<para>Le processus <varname>LIST</varname> est exécuté avec ses entrées et sorties connectées à un tube ou des fichiers dans <filename>/dev/fd</filename>.  Le nom de ce fichier est passé en argument à la commande courante comme le résultat de l'expansion.  Si la forme <quote>&gt;(LIST)</quote> est employée, d'écrire dans le fichier alimente l'entrée de <varname>LIST</varname>.  Si la forme <quote>&lt;(LIST)</quote> est employée, le fichier passé en argument devrait être lu pour obtenir la sortie de <varname>LIST</varname>.  Notez qu'aucun espace ne doit apparaître entre le signe &lt; ou &gt; et la parenthèse gauche, sinon la construction serait interprétée comme une redirection.</para>
<para>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.</para>
<para>Plus de détails à la <xref linkend="sect_08_02_03" />.</para>
</sect2>
<sect2 id="sect_03_04_07"><title>Le découpage de mots</title>
<para>Le Shell<indexterm><primary>expansion</primary><secondary>word splitting</secondary></indexterm> 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.</para>
<para>Le Shell<indexterm><primary>word splitting</primary><secondary>input field separator</secondary></indexterm> traite chaque caractère de  <varname>$IFS<indexterm><primary>variables</primary><secondary>IFS</secondary></indexterm></varname> comme un délimiteur, et découpe le résultat des autres expressions en mots sur la base de ces caractères.  Si <varname>IFS<indexterm><primary>input field separator</primary><secondary>word splitting</secondary></indexterm></varname> n'est pas déclaré, ou si il vaut exactement  <quote>'&lt;space&gt;&lt;tab&gt;&lt;newline&gt;'</quote>, sa valeur par défaut, alors toute suite de caractères <varname>IFS</varname> sert à délimiter les mots.   Si <varname>IFS</varname> Si <varname>IFS</varname> a une valeur autre que celle par défaut, alors les suites d'<quote>espace</quote> et <quote>Tab</quote> sont ignorées au début et à la fin du mot, du moment que l'espace est inclut dans <varname>IFS</varname> (un caractère espace  <varname>IFS</varname>).  Tout caractère dans <varname>IFS</varname> qui n'est pas un espace  <varname>IFS</varname>, accolé à un caractère espace <varname>IF</varname>, délimite un champ.  Une suite de caractère espace <varname>IFS</varname> est aussi traitée comme un délimiteur.  Si la valeur de <varname>IFS</varname> est nulle, le découpage en mots n'intervient pas.</para>
<para>Un argument vide<indexterm><primary>arguments</primary><secondary>null arguments</secondary></indexterm> (<quote>""</quote> or <quote>''</quote>) 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é.</para>
<note><title>Expansion et découpage en mots</title><para>Si aucune expansion ne se produit, aucun découpage n'est effectué</para></note>
</sect2>
<sect2 id="sect_03_04_08"><title>Expansion de noms de fichier</title>
<para>Après le découpage en mots<indexterm><primary>expansion</primary><secondary>file name expansion</secondary></indexterm>, à moins que l'option <option>-f</option> ait été utilisée (voir <xref linkend="sect_02_03_02" />), Bash scanne chaque mot pour les caractères <indexterm><primary>file name expansion</primary><secondary>characters</secondary></indexterm> <quote>*</quote>, <quote>?</quote>, et <quote>[</quote>  Si l'un de ces caractères apparaît, alors le mot est considéré comme étant un <emphasis>PATRON</emphasis>, 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 <option>nullglob<indexterm><primary>options</primary><secondary>nullglob</secondary></indexterm></option> est désactivée, le mot est laissé en l'état.  Si l'option <option>nullglob</option> est activée, et qu'aucune correspondance n'est trouvée, le mot est éliminé.  Si l'option Shell<indexterm><primary>options</primary><secondary>nocaseglob</secondary></indexterm> <option>nocaseglob</option> est activée, la correspondance est recherchée sans considérer la casse des caractères alphabétiques.</para>
<para>Quand un patron sert à la génération de noms de fichiers, le caractère <quote>.</quote> 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 <option>dotglob</option> 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 <quote>.</quote> n'est pas traité spécifiquement.</para>
<para>La variable Shell  <varname>GLOBIGNORE<indexterm><primary>variables</primary><secondary>GLOBIGNORE</secondary></indexterm></varname> peut être utilisée pour restreindre l'ensemble de fichiers en correspondance avec le patron.  Si <varname>GLOBIGNORE</varname> est activé, les noms qui correspondent à l'un des patrons dans <varname>GLOBIGNORE</varname> sont retirés de la liste de correspondance.  Les noms de fichiers <filename>.</filename> et <filename>..</filename> sont toujours ignorés, même si <varname>GLOBIGNORE</varname> est désactivé.  Cependant, déclarer<varname>GLOBIGNORE</varname> a pour effet d'activer l'option Shell <option>dotglob</option>, donc tous les autres fichiers commençant par <quote>.</quote> correspondront.  Pour garder la possibilité d'ignorer les fichiers commençant par  <quote>.</quote>, indiquer <quote>.*</quote> comme étant un des patrons à ignorer dans  <varname>GLOBIGNORE</varname>.  L'option <option>dotglob</option> est désactivé quand <varname>GLOBIGNORE</varname> n'est pas déclaré.</para>
</sect2>

</sect1>

<sect1 id="sect_03_05"><title>Alias</title>
<sect2 id="sect_03_05_01"><title>Que sont les alias&nbsp;?</title>

<para>

Un alias<indexterm><primary>alias</primary></indexterm> 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<indexterm><primary>aliases</primary><secondary>definition</secondary></indexterm> 
qui sont déclarés ou invalidés avec les intégrées 
<command>alias</command> et <command>unalias</command> 
<indexterm><primary>aliases</primary><secondary>delete an 
alias</secondary></indexterm>. Saisir <command>alias</command> sans 
options pour afficher une liste des alias connus du Shell 
courant<indexterm><primary>aliases</primary><secondary>examples</secondary></indexterm>.

</para>

<screen>
<prompt>franky: ~&gt;</prompt> <command>alias</command>
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 &amp;'

<prompt>franky ~&gt;</prompt>
</screen>
<para>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 <indexterm><primary>aliases</primary><secondary>usage</secondary></indexterm> est de permettre la correction des fautes de frappes.</para>
<para>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 <quote>=</quote>.  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 <command>ls</command> équivalent à <command>ls <option>-F</option></command>, 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.</para>
<para>Les alias ne sont pas remplacés quand le Shell n'est pas interactif, sauf si l'option <option>expand_aliases</option> est activée<indexterm><primary>aliases</primary><secondary>expand_aliases</secondary></indexterm> par l'intégrée <command>shopt</command> shell.</para>
</sect2>
<sect2 id="sect_03_05_02"><title>Créer et supprimer des alias</title>
<para>Un alias est créé par l'intégrée <command>alias</command> <indexterm><primary>aliases</primary><secondary>creation</secondary></indexterm>.  Pour une déclaration permanente, ajouter la commande <command>alias</command> dans l'un de vos scripts d'initialisation&nbsp;; si vous l'entrez seulement sur la ligne de commande, il sera connu que durant la session.</para>
<screen>
<prompt>franky ~&gt;</prompt> <command>alias <parameter>dh='df -h'</parameter></command>

<prompt>franky ~&gt;</prompt> <command>dh</command>
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

<prompt>franky ~&gt;</prompt> <command>unalias <parameter>dh</parameter></command>

<prompt>franky ~&gt;</prompt> <command>dh</command>
bash: dh: command not found

<prompt>franky ~&gt;</prompt>
</screen>
<para>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<indexterm><primary>aliases</primary><secondary>aliases in functions</secondary></indexterm> 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 <command>alias</command> dans des commandes composées.</para>
<para>Les processus enfants n'héritent pas des alias.  Bourne shell (<command>sh</command>) ne reconnaît pas les alias.</para>
<para>Plus sur les fonctions au <xref linkend="chap_11" />.</para>
<tip><title>Les fonctions sont plus rapides</title><para>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.</para></tip>

</sect2>

</sect1>
<sect1 id="sect_03_06"><title>Plus d'options Bash</title>
<sect2 id="sect_03_06_01"><title>Afficher les options</title>
<para>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.</para>
<para>Utilisez l'option <option>-o</option> de <command>set</command>  pour afficher toutes les options Shell<indexterm><primary>options</primary><secondary>display all options</secondary></indexterm>&nbsp;:</para>
<screen>
<prompt>willy:~&gt;</prompt> <command>set <option>-o</option></command>
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
</screen>
<para>Voir les pages Bash info, section <menuchoice><guimenu>Shell Built-in Commands</guimenu><guimenuitem>The Set Built-in</guimenuitem></menuchoice> pour une description de chaque option.  Beaucoup d'options ont un raccourci de un caractère&nbsp;: l'option <option>xtrace</option> , par exemple, équivaut à spécifier <command>set <option>-x</option></command>.</para>
</sect2>
<sect2 id="sect_03_06_02"><title>Changer les options</title>
<para>Les options Shell peuvent être modifiées<indexterm><primary>options</primary><secondary>changing options</secondary></indexterm> 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.</para>
<para>La commande suivante exécute un script en mode compatible POSIX&nbsp;:</para>
<screen>
<prompt>willy:~/scripts&gt;</prompt> <command>bash <option>--posix</option> <filename>script.sh</filename></command>
</screen>
<para>Pour changer l'environnement temporairement, ou à l'usage d'un script, nous utiliserions plutôt <command>set</command>. Employez <emphasis>-</emphasis> (moins) pour activer l'option, <emphasis>+</emphasis> pour la désactiver&nbsp;:</para>
<screen>
<prompt>willy:~/test&gt;</prompt> <command>set <option>-o</option> <parameter>noclobber</parameter></command>

<prompt>willy:~/test&gt;</prompt> <command>touch <filename>test</filename></command>

<prompt>willy:~/test&gt;</prompt> <command>date &gt; <filename>test</filename></command>
bash: test: cannot overwrite existing file

<prompt>willy:~/test&gt;</prompt> <command>set <option>+o</option> <parameter>noclobber</parameter></command>

<prompt>willy:~/test&gt;</prompt> <command>date &gt; <filename>test</filename></command>
</screen>
<para>L'exemple ci-dessus montre l'usage de l'option <option>noclobber</option> <indexterm><primary>options</primary><secondary>noclobber</secondary></indexterm>, 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 <option>-u</option>, qui, activée, traite les variables non déclarées comme des erreurs, et quitte un Shell non-interactif quand survient une telle erreur&nbsp;:</para>
<screen>
<prompt>willy:~&gt;</prompt> <command>echo <varname>$VAR</varname></command>


<prompt>willy:~&gt;</prompt> <command>set <option>-u</option></command>

<prompt>willy:~&gt;</prompt> <command>echo <varname>$VAR</varname></command>
bash: VAR: unbound variable
</screen>
<para>Cette option est aussi utile pour détecter des valeurs incorrectes<indexterm><primary>variables</primary><secondary>detect content assignment</secondary></indexterm> affectées à des variables&nbsp;: 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.</para>
<para>Voici un dernier exemple qui illustre l'option <option>noglob</option> , laquelle empêche les caractères spéciaux d'être interprétés&nbsp;:</para>
<screen>
<prompt>willy:~/testdir&gt;</prompt> <command>set <option>-o</option> <parameter>noglob</parameter></command>

<prompt>willy:~/testdir&gt;</prompt> <command>touch <filename>*</filename></command>

<prompt>willy:~/testdir&gt;</prompt> <command>ls <option>-l</option> <filename>*</filename></command>
-rw-rw-r--    1 willy    willy          0 Feb 27 13:37 *
</screen>
</sect2>

</sect1>


<sect1 id="sect_03_07"><title>Résumé</title>
<para>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.</para>
<para>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.</para>
<para>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.</para>
<para>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é.</para>
<para>Bash emploie diverses méthodes pour l'expansion de la ligne de commande afin de déterminer quelle est la commande à exécuter.</para>

</sect1>
<sect1 id="sect_03_08"><title>Exercices</title>
<para>Pour cet exercice, vous aurez besoin de lire les pages man de <command>useradd</command>, parce que nous allons utiliser le répertoire <filename>/etc/skel</filename> pour stocker les fichiers de configuration Shell par défaut, lesquels sont copiés dans le répertoire racine de chaque utilisateur ajouté.</para>
<para>D'abord nous ferons quelques exercices de portée générale sur la déclaration et l'affichage de variables.</para>

<orderedlist>
<listitem><para>Créer 3 variables, <varname>VAR1</varname>, <varname>VAR2</varname> et <varname>VAR3</varname>&nbsp;; les initialiser respectivement aux valeurs <quote>thirteen</quote>, <quote>13</quote> et <quote>Happy Birthday</quote>.</para></listitem>
<listitem><para>Faire afficher les valeurs des ces 3 variables.</para></listitem>
<listitem><para>Sont-elles des variables locales ou globales&nbsp;?</para></listitem>
<listitem><para>Supprimer <varname>VAR3</varname>.</para></listitem>
<listitem><para>Pouvez-vous voir les 2 variables restantes dans la nouvelle fenêtre d'un autre terminal&nbsp;?</para></listitem>
<listitem><para>Modifier <filename>/etc/profile</filename> pour que tous les utilisateurs soient accueillis à la connection (tester).</para></listitem>
<listitem><para>

Pour le compte <emphasis>root</emphasis>, modifier l'invite pour que 
s'affiche <quote>Danger&nbsp;!! root travaille en mode \w</quote>, de 
préférence une couleur vive telle que rouge ou rose ou le mode vidéo 
inversé.

</para></listitem>
<listitem><para>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.</para></listitem>
<listitem><para>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.</para></listitem>
</orderedlist>
<para>N'oubliez pas le <command>chmod</command> de vos scripts&nbsp;!</para>
</sect1>
</chapter>

Site hébergé sur un Cloud Public IKOULA Ikoula