1. Principes de fonctionnement de GNU/bash

1.1. Rôle d'un shell

Le shell est un interpréteur de commande en ligne. Chaque entrée sur un terminal est analysée et décomposée en terme d'instructions à exécuter. Ces instructions peuvent impliquer des commandes internes que le shell connaît et est en mesure d'exécuter directement, ou bien d'autres commandes déclenchant des programmes que le shell va tenter de localiser et de lancer. Le shell dispose d'instructions (structures de contrôle, ...) et de variables qui le rend, en partie, comparable à un langage de programmation, de sorte que l'on peut écrire des shell scripts, littérallement de petits ou moyens programmes rédigé en shell.

Un interpréteur shell exécutent trois types de commandes :

  1. Les commandes internes [built-in commands], comme par exemple : cd, pwd, umask ... ou bien encore les éléments algorithmiques tels if .. then .. else .. fi, for ... ...

  2. Les commandes externes indépendantes du shell et localisées dans les répertoires, comme par exemple : ls (/bin/ls), find (/usr/bin/find) ... Ces commandes nécessitent la création d'un nouveau shell pour leur exécution contrairement à celles relevant de la première catégorie.

  3. Les commandes définies par un alias ou par une fonction.

1.2. Caractéristiques de GNU/bash

  • il possède un mécanisme d'historisation, de rappel et d'éditions des commandes ;

  • il permet le contrôle des processus/jobs (suspension), reprise asynchrone (background) ou interactive (foreground)) ;

  • il permet de traiter les tableaux de caractères ;

  • il permet de définir des fonctions et des variables locales aux fonctions ;

  • il gère l'arithmétique des entiers dans les bases 2 à 64 ;

  • il possède un mécanisme de completion.

1.3. Fichiers de configuration de GNU/bash

Lors du login de connexion, GNU/bash exécute les instructions contenues dans le fichier /etc/profile puis celles du fichier ~/bash_profile s'il existe et sinon ~/.bash_login s'il existe (et sinon ~/.profile). Les scripts précédent peuvent éventuellement activer l'exécution de ~/.bashrc, lequel peut à son tour lancer /etc/bashrc. La signification du caractère ~ est donnée en Section 1.5, « Métacaractères et autres caractères spéciaux du shell ». Lors de la fin de session (logout) GNU/bash exécutent les commandes du fichier ~/bash_logout.

Un sous-shell, ne lit que le fichier ~/.bashrc à son démarrage et rien à sa terminaison.

De ce qui précède, on déduit que les commandes à exécuter une seule fois pendant une session sont à placer dans le fichier ~/.bash_profile (typiquement les variables d'environnement), tandis que les autres sont à placer dans le fichier ~/.bashrc.

Le fichier ~/.bash_profile contient essentiellement la définition des variables d'environnement.

Exemple 1.  fichier ~/.bash_profile


# ~/.bash_profile: executed by bash(1) for login shells.                        
# see /usr/share/doc/bash/examples/startup-files for examples.
# the files are located in the bash-doc package.

umask 0077

export EDITOR=emacs
export LANG=fr_FR@euro
export LC_CTYPE=fr_FR.ISO8859-15
export PAGER=less

# include .bashrc if it exists
if [ -f ~/.bashrc ]; then
    source ~/.bashrc
fi

# set PATH so it includes user's private bin if it exists
if [ -d ~/bin ] ; then
    PATH=~/bin:"${PATH}"
fi

# do the same with MANPATH
#if [ -d ~/man ]; then
#    MANPATH=~/man:"${MANPATH}"
#fi

Le fichier ~/.bashrc contient typiquement :

  • la définition des alias ;

  • la définition des paramètres de fonctionnement ;

  • l'initialisation des variables.

Exemple 2. fichier ~/.bashrc


# ~/.bashrc: executed by bash(1) for non-login shells.
# see /usr/share/doc/bash/examples/startup-files (in the package bash-doc)      
# for examples

# If running interactively, then:
if [ "$PS1" ]; then

    # don't put duplicate lines in the history. See bash(1) for more options
    # export HISTCONTROL=ignoredups

    # enable color support of ls and also add handy aliases
    eval `dircolors -b`
    alias ls='/bin/ls --color=auto'
    #alias dir='ls --color=auto --format=vertical'
    #alias vdir='ls --color=auto --format=long'

    # some more ls aliases
    alias ll='ls -l'
    alias la='ls -A'
    alias l='ls -CF'
    alias rm='/bin/rm -i'

    # set a fancy prompt
    PS1='\u@\h:\w\$ '

    # If this is an xterm set the title to user@host:dir
    #case $TERM in
    #xterm*)
    #    PROMPT_COMMAND='echo -ne "\033]0;${USER}@${HOSTNAME}: ${PWD}\007"'
    #    ;;
    #*)
    #    ;;
    #esac

    # enable programmable completion features (you don't need to enable
    # this, if it's already enabled in /etc/bash.bashrc).
    #if [ -f /etc/bash_completion ]; then
    #  . /etc/bash_completion
    #fi

    /usr/bin/X11/xrdb -load ~/.Xdefaults >& /dev/null
fi

Le fichier ~/.bash_logout contient essentiellement des commandes de suppression de fichiers inutiles, exécutées typiquement à la déconnexion.

Exemple 3.  fichier ~/.bash_logout


# ~/.bash_logout

echo -n "clean up before logout ..."
find $HOME \( -type f \
              \( -name a.out -o -name "*.bak" -o -name core  -o \
                 -name "#*#" -o -name "#.*#"  -o -name "*.o" -o \
                 -name "*~"  -o -name ".*~" \) -exec /bin/rm -f {} \; > /dev/nul
l \)
echo "... done" 
echo "last connexion at [`date +%Y-%m-%d` a `date +%H:%M:%S`] pour [`logname`] s
ur [`tty`]" > ~/.deconnex

Q : Quel est le rôle de la commande find dans le contexte du listing précédent (~/.bash_logout) ?
Q :

Quel est le rôle de la commande find dans le contexte du listing précédent (~/.bash_logout) ?

R :

Il est possible à tout moment et notamment après une modification de réexécuter les fichiers au moyen de la commande source (l'exécution se fait dans le contexte du shell courant, i.e. modification de l'environnement courant).

$ source ~/.bash_profile                                                        
$ source ~/.bashrc

1.4.  Variables d'environnement

On parle de variables d'environnement car elles sont « automatiquement » transmises à tous les processus fils du shell, i.e. tous les processus lancés par ce shell.

Les variables qui suivent ont un sens particulier pour le shell (GNU/bash), elles sont utilisées par certaines commandes du shell ou du système.

Tableau 1.  Variables d'environnement

Variable d'environnement Sémantique
BASHDonne le chemin absolu du shell (typiquement /bin/bash).
BASH_VERSION Donne la version du shell (ici 2.05b.0(1)-release).
CDPATHListe des répertoires explorés par la commande cd.
EUIDUID (identifiant) effectif de l'utilisateur courant.
FIGNORE Liste de suffixes de fichiers qui ne doivent pas apparaître dans l'expansion. (typiquement *~:*.o:*.bak)
HISTCMD Numéro de la commande courante dans l'historique.
HISTCONTROLPeut prendre trois valeurs : « ignoredups », « ignorespace », « ignoreboth » de sémantique respective suivante : la ligne courante n'est pas rajoutée à l'historique si elle est identique à la précédente, une ligne commençant par un blanc n'est pas ajoutée à l'historique, enfin la dernière combine les deux précédentes.
HISTFILELe fichier historique (typiquement ~/.bash_history).
HISTFILESIZENombre de lignes maximum de l'historique (par défaut 500).
HISTSIZENombre de commandes mémorisées par la commande history (par défaut 500).
HOSTNAMENom (court) de la machine.
HOSTTYPEArchitecture de la machine (pour un PC i386).
HOMEDésigne le répertoire de localisation de celui qui invoque la commande. L'expansion de nom de fichier ~ se réfère à cette variable.
IFS(Internal Field Separator) Contient le/les séparateur(s) de champs, par défaut « <space><tab><newline> ».
IGNOREEOFContrôle l'action du shell interactif sur réception du caractère EOF. Si cette variable est positionnée (numériquement), elle correspond au nombre consécutif de caractères EOF à taper sur la ligne courante pour sortir de GNU/bash. Sa valeur par défaut est de 10 si la variable existe, sinon elle signifie la fin d'une entrée pour le shell.
MAILIndique le fichier dans lequel le shell contrôle l'arrivée de nouveaux messages.
MAILCHECKDéfinit la fréquence de vérification d'arrivée de nouveaux couriers (par défaut 60s, i.e. une vérification toutes les minutes).
PATH Définit l'ensemble des chemins dans lesquels le shell recherche les commandes externes à exécuter.
PPID PID (Process IDentifier) père du processus courant.
PS1Définit l'invite de commandes en mode interactif (par défaut $).
PS2Définit l'invite de commandes secondaire en mode interactif (par défaut >).
PS3Définit l'invite de la structure de boucle select (par défaut #?).
PS4Définit l'invite de trace (par défaut +).
PWDChemin absolu du répertoire courant.
RANDOMA chaque appel à cette variable un entier dans l'intervalle [0..32767] est aléatoirement généré.
SECONDSTemps écoulé en secondes depuis le lancement du shell courant.
SHLVLNombre d'instance(s) de shell lancé(s).
UIDIdenfifiant de l'utilisateur courant.
NO_CLOBBER Modifie la sémantique des commandes de redirections > et >> permettant ainsi d'éviter un effacement accidentel. L'utilisation de > renvoit une erreur si le fichier existe. Quand à >>, elle se réfère uniquement aux fichiers existants.

1.5. Métacaractères et autres caractères spéciaux du shell

Les métacaractères jouent le rôle de classe de représentation des fichiers dans le contexte du répertoire courant si rien n'est précisé ou bien dans celui du répertoire explicitement nommé.

  • Le caractère ~ placé en première position désigne le répertoire personnel de l'utilisateur courant :

    
    $ echo ~                                                                        
    /home/pascal
    
    $ ls -l ~/documentation
    total 3
    drwx------  6 pascal  gnu  512 Mar 14 14:43 LaTeX
    drwx------  4 pascal  gnu  512 Mar 28 16:06 docbook
    drwx------  2 pascal  gnu  512 Mar 20 22:20 docbook-slides
    
    

  • Le caractère * est substituable par n'importe quelle combinaison de 0 ou plusieurs caractères.

    Exemple : Lister l'ensemble des fichiers commençant par le motif C-csh_n_tcsh du répertoire courant :

    
    $ ls C-csh_n_tcsh*                                                              
    C-csh_n_tcsh.fo  C-csh_n_tcsh.pdf C-csh_n_tcsh.ps  C-csh_n_tcsh.xml  
              
    

    Exemple : Lister les fichiers (non cachés) du répertoires courant :

    
    $ echo *                                                                        
    C-csh_n_tcsh.fo C-csh_n_tcsh.pdf C-csh_n_tcsh.ps C-csh_n_tcsh.xml Makefile      
    _mystyle.css _mystyle.xsl html images my_print.dsl release test.sh test.tgz
     
    

    [Avertissement]Avertissement

    Les fichiers commençant par le caractère . ou fichiers cachés d'Unix™ [dot files] ne peuvent être remplacés par aucun caractère, i.e. le caractère « * » est inopérant.

  • Le caractère ? est substituable par un unique caractère quelconque.

    Exemple : Lister les fichiers commençant par le motif C-csh_n_tcsh et dont le suffixe est réduit à deux caractères :

    
    $ > echo C-csh_n_tcsh.??                                                        
    C-csh_n_tcsh.fo C-csh_n_tcsh.ps
                                                  
    
  • Les caractères [] permettent une substitution par un caractère parmi l'ensemble dénoté par les crochets.

    Exemple : Lister les fichiers cachés du répertoire $HOME de l'utilisateur courant, dont le second caractère est compris entre 'a' et 'e' :

    
    $ ls -d ~/.[a-e]*                                                               
    /home/pascal/.acrobat        /home/pascal/.cshrc          /home/pascal/.emacs.d
    /home/pascal/.acrorc         /home/pascal/.cvsrc          /home/pascal/.esd
    /home/pascal/.adobe          /home/pascal/.deconnex       /home/pascal/.esd_auth
    /home/pascal/.autosave       /home/pascal/.dia            /home/pascal/.exit.log
    /home/pascal/.bash_history   /home/pascal/.emacs
    
    

    Autre exemple, utilisation de la négation, marquée par le caractère ^ : lister les fichiers cachés du répertoire $HOME de l'utilisateur courant, dont le second caractère n'est ni '.', ni 'a', ni 'b', ni 'c', ni 'd' ni 'e' (le premier étant un '.') :

    
    $ ls -d ~/.[^.a-e]*                                                             
    /home/pascal/.fetchmail.pid                /home/pascal/.profile.rc             
    /home/pascal/.fetchmailrc                  /home/pascal/.ressources
    /home/pascal/.fonts.cache-1                /home/pascal/.rhosts
    /home/pascal/.fr                           /home/pascal/.shadow_todo
    /home/pascal/.gkrellm                      /home/pascal/.shrc
    /home/pascal/.gnupg                        /home/pascal/.sversionrc
    /home/pascal/.gv                           /home/pascal/.tcsh_comp
    /home/pascal/.history                      /home/pascal/.themeinstaller
    /home/pascal/.ispell_francais              /home/pascal/.user60.rdb
    /home/pascal/.login                        /home/pascal/.weblink
    /home/pascal/.logout                       /home/pascal/.xemacs
    /home/pascal/.mail_aliases                 /home/pascal/.xfigrc
    /home/pascal/.mailcap                      /home/pascal/.xinitrc
    /home/pascal/.mailrc                       /home/pascal/.xmms
    /home/pascal/.mgprc                        /home/pascal/.xsession
    /home/pascal/.mime.types                   /home/pascal/.xsession-errors
    /home/pascal/.mozilla                      /home/pascal/.xwm.msgs
    /home/pascal/.mutt
    
    

  • Les caractères { } permettent la substitution par un mot de l'énumération dénotée par les accolades.

    Exemple : Lister les fichiers se terminant par les suffixes .xml et .pdf et .fo :

    
    $ ls C-csh_n_tcsh.{xml,pdf,fo}                                                  
    C-csh_n_tcsh.fo  C-csh_n_tcsh.pdf C-csh_n_tcsh.xml                              
    
    

  • Quelques autres caractères spéciaux

    Tableau 2. Autres caractères spéciaux du shell

    Caractère Sémantique
    ;Séparateur de commande, i.e. opérateur de séquentialité.
    &Séparateur de commande qui place la commande qui le précède en arrière-plan, i.e. en exécution asynchrone.
    \Quote le caractère qui le suit et notamment pour les caractères spéciaux, inhibe leur sémantique particulière.
    $Accède au contenu de la variable qui le suit immédiatement.
    '[quote] Quote le texte qui le suit jusqu'au ' fermant.
    `[backquote] Considère le texte quoté comme une commande et la remplace par le résultat de son évaluation.
    "[double quote] Quote le texte qui le suit en interpolant les éventuelles variables qu'il contient.
    !Substitution dans l'historique.
    |Tube [pipe].
    > et >>Redirection de la sortie standard.
    < et <<Redirection de l'entrée standard.
    #Marque le début d'un commentaire, i.e. pas d'expansion.
    &&Et [And] logique.
    ||Ou [Or] logique.