Csh & TCsh

Pascal Picard

Corto E.T.F., K&M

Sainte-Clotilde, Ile de la Réunion

Ivan Kurzweg

Fremens Inst.

La Possession, Ile de la Réunion

$Id: C-csh_n_tcsh.xml,v 1.1.1.1 2006/04/02 16:27:31 Ivan Exp $

Permission to use, copy, modify, and distribute this documentation for any purpose with or without fee is here by granted, provided that the above copyright notice and this permission notice appear in all copies.

THE DOCUMENTATION IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS DOCUMENTATION INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS DOCUMENTATION.


1. Principes de fonctionnement de csh
1.1. Rôle d'un shell
1.2. Caractéristiques de csh
1.3. Fichiers de configuration de csh
1.4. Variables prédéfinies et d'environnement
1.5. Métacaractères et autres caractères spéciaux du shell
2. Les commandes internes
2.1. source
2.2. setenv/unsetenv
2.3. set/unset
2.4. alias/unalias
2.5. umask
2.6. Historique
2.7. Completion
2.8. Navigation dans les répertoires
2.8.1. Commandes cd
2.8.2. Pile de répertoires : pushd, popd et dirs
2.9. Gestion des processus
2.9.1. Les processus
2.9.2. Les signaux
2.9.3. Jobs
2.9.4. limit
2.10. Redirection de commandes
2.11. Tubes [Pipelines]
3. Structures de Contrôle & autres éléments algorithmiques
3.1. Alternatives
3.1.1. La structure alternative if
3.1.2. La structure alternative switch
3.2. Boucles
3.2.1. Boucle while
3.2.2. Boucle repeat
3.2.3. Boucle foreach
3.3. Variables utilisateurs
3.4. Paramètres du shell
3.5. Lecture sur l'entrée standard
3.6. Expressions conditionnelles
4. Les apports de TCsh
4.1. Completion étendue
4.2. bindkey
4.3. Spelling Correction
5. Exercices
Références

Résumé

Le shell est d'abord l'interpréteur de commande d'un système Unix™ mais c'est aussi un quasi langage de programmation interpreté autorisant la récursivité.

Historiquement le premier shell du système Unix™ est le Bourne-Shell (sh). Ce shell n'a cessé d'être amélioré et l'université de Berkeley qui a beaucoup contribué à la branche BSD d'Unix™ a développé le C-Shell (csh), un successeur de sh munit de fonctionnalités étendues par rapport à son ancêtre. Le C-Shell à son tour possède un successeur : TC-Shell (tcsh), ce dernier étend les fonctionnalités de son prédécesseur et apporte davantage de convivialité. Ces caractéristiques en font un équivalent au GNU Bourne-Again-Shell (GNU/bash).

Ces shells syntaxiquement orientés C restent les shells par défaut des flavors BSD et c'est pourquoi nous nous proposons, dans ce support, de les présenter principalement dans un contexte d'interactivité où ils sont plutôt efficaces.

Pour nous joindre :

1. Principes de fonctionnement de csh

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 rende 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 .. endif, foreach ... ...

  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.

1.2. Caractéristiques de csh

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

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

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

  • il possède des directives de programmation proche du C ;

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

  • il permet le calcul arithmétique.

1.3. Fichiers de configuration de csh

Lors du login, csh exécute les instructions contenues dans le fichier /etc/csh.cshrc puis celles du fichier /etc/csh.login puis celles de ~/.cshrc (tcsh lit le script ~/.tcshrc, s'il existe et sinon ~/.cshrc) et enfin celles de ~/.login. 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) csh ou tcsh exécutent les commandes des fichiers /etc/csh.logout et ~/.logout, dans cet ordre.

Un sous-shell, ne lit pas les fichiers suffixés en .login à son démarrage ni les fichiers suffixés en .logout à 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 les fichiers suffixés en .login (typiquement les variables d'environnement), tandis que les autres sont à placer dans les fichiers suffixés en .cshrc.

Le fichier ~/.cshrc contient typiquement :

  • la définition des alias ;

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

  • l'initialisation des variables.

Exemple 1. fichier ~/.cshrc


# ~/.cshrc
#
# $FreeBSD: src/share/skel/dot.cshrc,v 1.10.2.3 2001/08/01 17:15:46 obrien Exp $#
# .cshrc - csh resource script, read at beginning of execution by each shell
# see also csh(1), environ(7).
#

# Les alias
# -------------------------
alias j         jobs -l
alias la        /bin/ls -aoBG
alias lf        /bin/ls -FABG
alias ll        /bin/ls -loABG
alias gv        /usr/X11R6/bin/gv -color -safer -quiet \ 
-media a4 -portrait
alias rm        /bin/rm -i
alias wget      `which wget` -N -c -S
alias emacs     `which emacs` -q
alias gnuplot   `which gnuplot` -background ivory
alias xdvi      `which xdvi` -fg DarkSlateGray  -paper a4 
alias xfig      `which xfig` -center -centim -pap a4 -po
alias dvips     `which dvips` -t a4 -o out.ps
alias h         'history -r \!* | less'
alias psnup     `which psnup` -pa4 -2up -m0.5cm

# Paramètres et variables.
# -------------------------
limit coredumpsize 0  # prevent core files from being written to disc
# A righteous umask
umask 077
set prompt='%B%n%b@%m:%c > '
set prompt2='%B%n%b:>> '
set path = (/usr/local/sbin /usr/local/bin /sbin /bin /usr/sbin \
/usr/bin /usr/X11R6/bin $HOME/bin)
set correct = cmd

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

if ($?prompt) then
        # An interactive shell -- set some stuff up
        set filec
        set history = 2048
        set savehist = 2048
        set histfile = ~/.history
        set mail = (/var/mail/$USER)
        set notify      
        set addsuffix
        set autolist
        set machbeep = nomatch
        set cdpath = ( ~ ~/bin )
        set symlinks = ignore
        if ( $?tcsh ) then
                set echo_style = both
                set histdup = all
                set savehist = ( 2000 merge )
                bindkey "^W" backward-delete-word
                bindkey -k up history-search-backward
                bindkey -k down history-search-forward
                source ~/.tcsh_comp
        endif
endif

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

Exemple 2. fichier ~/.login


# ~/.login                                                                      

setenv LC_CTYPE fr_FR.ISO8859-15
setenv PAGER less
setenv MOZILLA_HOME /usr/X11R6/bin/mozilla
setenv MACHTYPE i386
setenv EDITOR emacs
setenv HOSTTYPE FreeBSD
setenv CPUTYPE k7
setenv OSTYPE FreeBSD
setenv TEXEDIT emacs
setenv VENDOR amd
setenv SHLVL 1
setenv LSCOLORS "ExFxbxcxBxdxHBhbafacad" 
setenv CLICOLOR 1
setenv CLICOLOR_FORCE 1

# COLORTERM to "rxvt"
setenv COLORTERM "rxvt"

# COLORFGBG to "default" 
setenv COLORFGBG "default" 

setenv RSYNC_RSH /usr/bin/ssh
setenv CVSROOT /home/cvsroot
setenv BLOCKSIZE       K
setenv TERM xterm-color

[ -x /usr/games/fortune ] && /usr/games/fortune freebsd-tips

Le fichier ~/.logout contient essentiellement des commandes de suppression de fichiers inutiles.

Exemple 3. fichier ~/.logout


# ~/.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:%I:%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 (~/.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.

$ > source ~/.login                                                             
$ > source ~/.cshrc

Avertissement

Dans les distributions xBSD on peut voir les deux fichiers suivants : /.login et /.profile (situés à la racine). Ils sont exécutés uniquement dans le mode mono-utilisateur [single-user mode]. Leurs modifications sont à faire avec le plus grand soin.

1.4. Variables prédéfinies et 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 (csh et tcsh), elles sont utilisées par certaines commandes du shell ou du système. Parmi elles, argv, cwd, home, path, prompt, shell et status sont toujours définies par le shell. Si l'on exclut les variables cwd et status, leur positionnement intervient seulement à l'initialisation. Ces variables ne sont plus modifiées, sauf éventuellement par l'utilisateur.

Tableau 1. Variables d'environnement

Variable d'environnementSémantique
argvArguments du shell, résultant de la substitution des paramètres positionnels. $argv[1] correspond à $1, $argv[2] à $2 ...
autologout[tcsh] Positionné à un certain nombre de minutes, permet de déconnecter automatiquement l'utilisateur au bout de cette période d'inactivité.
cdpathListe de répertoires alternatifs dans lesquels sera effectuée la recherche des sous-répertoires lors de l'utilisation de la commande cd avec un argument de type nom relatif.
correct[tcsh] Positionnable à all ou cmd. Dans le deuxième cas, permet la correction des erreurs de typos sur les noms de commandes.
cwdChemin absolu du répertoire courant.
echo 
filecPermet la completion des noms de fichiers.
histcharsChaîne de caractères à utiliser dans les substitutions de l'historique. Les éléments de cette chaîne remplacent les caractères standards, ainsi le premier caractère de cette chaîne remplace le '!', le second remplace le '^' ...
histfileChemin d'accès au fichier d'historique.
historyPermet de contrôler le nombre de lignes de l'historique. Noter que la dernière commande exécutée est toujours sauvegardée dans l'historique.
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.
ignoreeofLe positionnement de cette variable permet au shell d'ignorer le caractère de fin de fichier quand il est généré depuis un terminal. Cela permet donc d'immuniser le shell d'une fin accidentelle déclenchée par la séquence ^D (lire <CTRL>-D).
inputmode[tcsh] Définit le mode en insertion (par défaut) ou en overwrite pour l'édition de la ligne de commande .
mailIndique le fichier dans lequel le shell contrôle l'arrivée de nouveaux messages. Si la première valeur spécifiée dans mail est numérique, elle surcharge l'intervalle de temps entre chaque vérification, fixé par défaut à 10 minutes. Si la variable spécifie différents fichiers, chacun d'eux sera scruté pour détecter l'arrivée de nouveaux messages.
noclobberModifie 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.
noglobSi cette variable est positionnée, elle inhibe la fonctionnalité d'expansion des noms de fichiers. Surtout utile dans les scripts shell.
nonomatchSi cette variable est positionnée, il n'y a pas d'erreurs lorsque le mécanisme d'expansion des noms de fichiers ne correspond pas à tous les fichiers existants. Dans ce cas le motif est retourné.
notifySi positionné alors permet au shell de notifier de manière asynchrone la completion des jobs. Le comportement par défaut spécifie de présenter la completion des jobs avant d'imprimer le prompt.
pathDéfinit l'ensemble des chemins dans lesquels le shell recherche les commandes externes à exécuter.
promptDéfinit l'invite de commandes en mode interactif.
rmstar[tcsh] Si positionné, permet de demander à l'utilisateur confirmation lorsqu'il tape la commande rm *.
savehistSi l'argument est numérique, spécifie le nombre de lignes sauvegardées dans ~/.history, quand l'utilisateur se déloggue.
shellFichier dans lequel réside le shell.
shlvl[tcsh] Nombre de shell empilés, remis à 1 par un shell de login.
statusStatut retourné par la dernière commande exécutée.
timeSi cette variable est positionnée (valeur en secondes), alors toute commande dont la durée d'exécution dépasse cette valeur est suivie à sa terminaison de l'affichage de statistiques sur les temps utilisateur, système et réel consommés ainsi que le ratio temps utilisateur et temps système sur temps réel consommé.
verbose 

Relations entre variables du shell et les variables d'environnement. En csh comme en tcsh certaines variables du shell et des variables d'environnement sont maintenues à des valeurs identiques par le shell. Ce sont les variables user et USER, group et GROUP, home et HOME, term et TERM, path et PATH, et enfin shlvl et SHLVL.

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/.sysop
    
    $ ls -l ~/elemntBase
    total 3
    drwx------  6 sysop  gnu  512 Mar 14 14:43 Part1
    drwx------  4 sysop  gnu  512 Mar 28 16:06 Part2
    drwx------  3 sysop  gnu  512 Mar 20 22:20 Synthese
    
    
  • 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 xb*                                                              
    xba  xbc xbd xbe xbg xbf xbg xbh             
    
    

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

    $ > echo *
    xaa xab xac xad xae xaf xagxba  xbc xbd xbe xbg xbf xbg xbh xaa xab xac xad xae xaf xag
    

    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' (le premier étant le « . ») :

    
    $ 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 (extension tcsh) marqué 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èreSé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.
    '[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.

2. Les commandes internes

2.1. source

Cette commande exécute le fichier (et ces éventuels arguments) qui lui est passé en argument dans le shell courant (i.e. pas de fork et donc modification (éventuelle) du shell courant).


$ source ~/.login                                                               

2.2. setenv/unsetenv

La commande setenv permet d'initialiser une variable d'environnement, i.e. une variable qui sera transmise à tous les processus fils du shell.


setenv OSTYPE  FreeBSD                                                          
setenv CPUTYPE k7
setenv PAGER   less

La commande unsetenv permet de supprimer une variable d'environnement.

2.3. set/unset

La commande set a deux fonctions :

  • l'initialisation d'une variable :


$ set path=( $path ~/bin )                                                      

Cette déclaration permet d'enrichir la variable path du répertoire bin de l'utilisateur.

  • la déclaration d'une option :


$ set ignoreeof                                                                 

Cette option permet d'immuniser csh d'une destruction accidentelle. Il est normalement possible de clôre un terminal avec la séquence ^D (lire <CTRL>-D), mais si on positionne l'option ignoreeof la séquence précédente n'a plus d'effet.

La commande unset a évidement un effet symétrique. Elle permet donc de désarmer une option ou de supprimer une variable.

Important

La portée de ces actions est limitée au shell courant contrairement à la commande précédente (c.f. Section 2.2, « setenv/unsetenv »).

2.4. alias/unalias

Ce mécanisme permet de définir ou de redéfinir une commande. Exemple :


$ alias la /bin/ls -aoBG          # definition de l'alias la                    
$ alias rm /bin/rm -i             # definition de l'alias rm
$ alias                           # afficher les alias courants
la      (/bin/ls -aoBG)
rm      (/bin/rm -i)

En général, on place ces alias dans le fichier ~/.cshrc. Si on veut supprimer un alias on utilise la commande unalias comme suit :


$ unalias rm                                                                    
$ alias                                # afficher les alias courants
la      (/bin/ls -aoBG)

Pour ré-accéder à la commande masquée par son alias, comme dans l'exemple précédent où nous avons surchargé la commande classique rm, il suffit de :

  • Soit utiliser la commande par son nom absolu : /bin/rm.

  • Soit faire précéder la commande du caractère backslash (\), on tape donc toujours dans le cadre de l'exemple précédent : \rm

Q :

Que signifie la commande rm -i ?

R :

2.5. umask

Cette commande permet de spécifier (si elle est suivie d'un argument valide) ou d'afficher la valeur du masque de création des objets i.e. des fichiers.


$ umask  # affiche la valeur telle que prédéfinie dans ~/.cshrc                 
77       # autrement dir 0077   
$ umask 0027
$ umask
27       # autrement dit 0027

2.6. Historique

Ce mécanisme a pour rôle de mémoriser les n dernières commandes entrées, ce nombre étant un paramètre réglable. Cela permet de visualiser, d'éditer et/ou exécuter à nouveau les commandes mémorisées. La commande suivante permet d'activer l'historisation des commandes, elle signifie que les 512 dernières commandes seront mémorisées :


$ set history = 512                                                             

La commande suivante permet en plus de sauvegarder les m dernières commandes dans ~/.history au logout. Il est évident que m est au plus égale à n. Ici, nous ne retenons que les 256 dernières commandes :


$ set savehist = 256                                                            

La commande history permet d'afficher les commandes dans l'ordre de leur mémorisation.

 

$ history                                                                       
...
80  8:57    cp csh/Makefile Makefile.gen
81  9:03    more Makefile.gen
82  9:06    sed -e 's/SRCNAME=C-csh_n_tcsh/SRCNAME=/' Makefile.gen > Makefile   
83  9:07    xemacs createinf.sh
84  9:09    which mkdir
85  9:09    rm -rf html/ && make check && make html
86  9:10    ls -l csh/
87  9:12    echo $$

Pour relancer une commande, il suffit de l'appeler par son numéro (relativement à l'historique) en la préfixant par le caractère !. Par exemple, si on veut relancer la commande 84, il suffit de faire :


$ !84                                                                           
which mkdir
/bin/mkdir

Tableau 3. Quelques commandes de manipulation de l'historique

ExpressionSémantique
!!Répéter la dernière commande.
!nRépéter la commande numéro n.
!-nRépéter la nième précédent la dernière de l'historique, i.e. !-2 : avant dernière commande.
!texteRépéter la dernière commande commençant par texte.
!?texteRépéter la dernière commande contenant texte.
!:nRépéter le nième mot de la dernière commande.
!$Répéter le dernier mot de la dernière commande.
!*Répéter tous les arguments de la dernière commande.
^old^newRépéter la dernière commande en commençant par remplacer la première occurence de old par new.
!n:s^old^newRépéter la nième commande en commençant par remplacer la première occurence de old par new.
!n:gs^old^newRépéter la nième commande en commençant par remplacer toutes les occurences de old par new (substitution globale).

Pour terminer, il peut être intéressant de positionner l'alias suivant dans son ~/.cshrc.


alias h         'history -r \!* | less'                                         

Q :

Que signifie donc cet alias ?

R :

2.7. Completion

En csh la completion est activée par le positionnement de la variable d'environnement filec (c.f. « Section 1.4, « Variables prédéfinies et d'environnement » »). Ce mécanisme permet, selon le contexte, de compléter les noms de fichiers ou d'utilisateurs à partir de la saisie d'un préfixe suivi de la frappe du caractère « ESC ». Le contexte par défaut étant celui de fichiers.

Supposons, par exemple, que le contenu du répertoire courant soit le suivant :


_merge.pl       check.pl             fdate.sh             mytest.pl
_pidof.pl       crlf.pl              gen-meta-index.pl    replace_header_html.pl
_split.pl       extract.pl           idle.pl              rotate.pl
_test.pl        extract_piste.sh     logfile-1.2.pl       rsync.pl
bidir.pl        fcomp.sh             mylock.sh

Alors la séquence suivante : $ ls l<ESC> est résolue en (seule correspondance possible) : $ ls logfile-1.2.pl

Tandis que la séquence ci-contre : $ ls ext<ESC> est résolue partiellement en : $ ls extract suivit de l'émission d'un bip qui signale que cette expansion est incomplète puisque deux fichiers correspondent au préfixe saisi. La commande précédente suivie du <CTRL>-D permet d'obtenir l'ensemble des réponses potentielles :


$ ls extract<CTRL>-D                                                            
extract.pl*       extract_piste.sh*
$ ls extract

La saisie d'un seul caractère supplémentaire permet dans ce dernier cas de lever l'ambiguïté.

L'utilisation du bip (sonnerie du terminal) pour signaler des erreurs ou des correspondances potentielles peut être désactivée par le positionnement de la variable nobeep. Enfin, il est possible de limiter les correspondances potentielles à la completion en positionnant la variable fignore. Dans l'exemple suivant, on exclut des correspondances possibles les fichiers suffixés en .o, .out et *~.


$ set fignore = (.o .out *~)                                                    

Contexte utilisateur : le mécanisme de completion peut être utilisé pour compléter les noms d'utilisateurs. Il faut utiliser le préfixe ~ (il change le contexte de la completion) :


$ cd ~sys<ESC>                                                                   
$ cd ~sysop

2.8. Navigation dans les répertoires

2.8.1. Commandes cd

Supposons qu'un utilisateur ait souvent besoin de se rendre alternativement dans le répertoire /home/cvsroot/ et dans son propre répertoire ~/elemntBase, il peut alors :

  • pour se rendre en /home/cvsroot/C-network/, taper :


$ cd /home/cvsroot/C-network                                                    

  • et pour se rendre en ~/elemntBase, taper :


$ cd ~/elemntBase                                                                  
                                                              

Mais, cet utilisateur peut aussi se simplifier la vie en positionnant la variable cdpath, ainsi :


$ set cdpath = ( /home/cvsroot ~ )                                              

Ainsi, il peut se contenter de :

  • taper dans le premier cas :


$ cd C-network                                                                  
/home/cvsroot/C-network

  • et dans le second :


$ cd elemntBase                                                                    
~/elemntBase

2.8.2. Pile de répertoires : pushd, popd et dirs

Une pile est une structure de données qui permet de mémoriser des entrées et dont la stratégie d'accès est de type LIFO (Last In, First Out), i.e. on accède uniquement au sommet de la pile.

La pile des répertoires est gérée par les trois primitives suivantes :

  • La commande pushd qui permet de changer de répertoire (comme cd), en conservant l'ancien répertoire dans la pile (il est empilé).

  • La commande popd qui permet de changer de répertoire (comme cd), en dépilant le sommet de la pile.

  • La commande dirs qui permet d'afficher le contenu de la pile.

L'exemple suivant permet d'en comprendre le fonctionnement :

 
$ pwd 1 
/usr/home/.sysop/elemntBase/part4                               

$ pushd /usr/local/etc 2 
/usr/local/etc ~/elemntBase/part4

$ pwd 3 
/usr/local/etc

$ popd 4 
~/elemntBase/part4

$ pwd 5 
/usr/home/.sysop/elemntBase/part4

$ pushd /usr/local/etc
/usr/local/etc ~/elemntBase/part4

$ pwd 
/usr/local/etc

$ dirs -v 6 
0       /usr/local/etc
1       ~/elemntBase/part4

$ more =1/domains.txt 7
http://167.216.142.116
http://193.128.61.168
http://193.210.156.114

... encore plein de lignes...

1

Affiche le chemin courant.

2

Se rend dans le répertoire spécifié et l'empile au sommet de la pile.

3

Affiche le chemin courant.

4

Dépile le sommet et se rend dans le répertoire indiqué.

5

Affiche le chemin courant.

6

Affiche le contenu de la pile, en commençant par le sommet.

7

Utilisation de la pile pour lire un fichier situé hors du répertoire courant.

2.9. Gestion des processus

2.9.1. Les processus

Un processus est l'instance d'un programme en exécution. C'est une structure de données qui contient du code statique, des données statiques et dynamiques et un environnement d'exécution. Un processus possède un cycle de vie marqué par des états comme l'exécution (runnable), la suspension, l'attente, le sommeil, l'état zombie... Pour se voir allouer des tranches de temps (time slice) d'exécution sur le CPU, un processus doit être dans l'état exécutable.

Chaque programme démarré par le shell nécessite la création d'un nouveau processus, on a ainsi une arborescence de processus, puisqu'une nouvelle instance ne possède qu'un seul parent. L'utilitaire ps permet d'obtenir un instantané des processus en cours

$ > ps 
  PID 1  TT 2  STAT 3      TIME4 COMMAND 5

13123      p0-    I      0:03.58 xdiary
13124      p0-    I      0:00.31 xdalarm -cmdPipeId /var/tmp/tmp.0.B2ekTh
15124      p0     Is     0:00.28 -tcsh (tcsh)
16108      p0     S+     0:00.10 /usr/local/bin/wget -NSc ftp://ftp.openbsd.org/
15185      p1     Ss     0:00.38 -tcsh (tcsh)
15263      p1     S      0:43.71 xemacs C-csh_n_tcsh.xml (xemacs-21.1.14)
16109      p1     R+     0:00.00 ps
14204      p2     Is+    0:00.09 ssh -p 3322 -v pascal@Turing.corto.home
15534      p4     I+     0:00.28 mutt
52875      p4     Is     0:00.25 -tcsh (tcsh)
50861      p5     Is     0:00.25 -tcsh (tcsh)

1

Process Identifier, identifiant (unique) du processus.

2

TTy device, terminal d'exécution.

3

STATus, état du processus

4

TIME consumed, temps CPU consommé.

5

La commande exécutée.

Le système identifie chaque processus au moyen d'un entier appelé pid. Dans l'exemple précédent, la dernière ligne identifie le processus 50861 qui est un shell (tcsh) dans l'état idle, i.e. en sommeil depuis plus de 20 secondes, sur le terminal /dev/ttyp5.

La consultation du man 1 ps permet d'obtenir une explication complète de la commande. Je rappelle ici la sémantique BSD associée au premier caractère de la colonne STAT :

Tableau 4. Sens des éléments de la colonne STAT

CaractèreSémantique
DProcessus en attente d'une E/S disque.
IProcessus en sommeil depuis plus de 20 secondes.
RProcessus en exécution sur le CPU.
SProcessus en sommeil depuis moins de 20 secondes.
TProcessus suspendu (stoppé)
ZProcessus Zombie

Des caractères additionnels permettent d'avoir des informations supplémentaires, citons le + qui indique un processus d'avant plan (interactif [foreground]) parmi le groupe de processus contrôlé par un terminal.

La commande ps l (c.f. exemple suivant) permet d'obtenir plus de détails sur les processus. On y trouve les paramètres suivants :

  • l'uid : propriétaire du processus,

  • le pid : identifiant du processus,

  • le ppid : identifiant du père du processus,

  • le cpu : estimation du temps CPU consommé,

  • le pri : i.e. priorité d'ordonnancement,

  • le nice : priorité assignée par nice ; la modification de cette valeur permet d'influer sur l'algorithme d'ordonnancement [scheduling],

  • le vsz : donne la taille de la mémoire virtuelle utilisée (exprimée en kilo-octet),

  • le rss : taille de la mémoire réelle utilisée (exprimée en kilo-octet).

  • le wchan : le canal d'attente, i.e. l'adresse d'une structure de données identifiant la ressource ou l'évènement pour lequel le processus est en attente,

  • le state : état du processus parmi (R, S, I, Z ...),

  • le tt : le terminal associé au processus,

  • le time : temps cpu accumulé (utilisateur et système),

  • enfin la commande elle-même.


$ ps l
UID   PID  PPID CPU PRI NI   VSZ   RSS   WCHAN  STAT  TT     TIME COMMAND
666 13123     1   0   2  0  6424  5212   poll   S     p0- 0:07.40 xdiary
666 13124 13123   0   2  0  4956  3132   poll   S     p0- 0:00.76 xdalarm -cmdPi
666 15185 15182   0  18  0  2048  1684   pause  Ss    p1  0:00.57 -tcsh (tcsh)
666 20568 15185   0   2  0 13820  12388  poll   S     p1  0:05.60 xemacs C-csh_n
666 20596 15185   0  28  0   420   208   -      R+    p1  0:00.00 ps -l
666 14204 14203   0   2  0  2080  1500   select Ss+   p2  0:00.19 ssh -p 3322 -v
666 17975 17972   0   3  0  2048  1676   ttyin  Is+   p3  0:00.22 -tcsh (tcsh)
666 19717 52875   0   2  0  3868  2932   poll   S+    p4  0:00.42 mutt
666 52875 52872   0  18  0  2044  1664   pause  Is    p4  0:00.25 -tcsh (tcsh)
666 50861 50858   0  18  0  2044  1672   pause  Is    p5  0:00.26 -tcsh (tcsh)

L'invocation d'un programme déclenche un nouveau processus chargé de son exécution et pendant ce temps, le shell (père du processus) est suspendu jusqu'à la terminaison de ce processus. On parle alors d'éxecution interactive (ou en avant-plan [foreground]). Il est évidement possible d'exécuter un processus de manière asynchrone [background], i.e. de permettre au shell d'exécuter de nouvelles commandes immédiatement. Il suffit pour se faire de postfixer la commande à exécuter de manière asynchrone par le caractère « ampersand » : &. Voici un exemple (noter le numéro du processus : 20713) :


$ fetchmail &                                                                   
[2] 20713

csh a introduit la notion de suspension d'un processus interactif par la commande ^Z (lire <CTRL>-Z). La reprise peut se faire de manière asynchrone (arrière plan) par la commande bg ou de manière interactive (avant plan) avec la commande symétrique fg.

Pour finir, signalons la commande top qui permet d'avoir des informations en temps réel sur les processus (rafraîchissement toutes les 2 secondes). En voici un exemple tronqué :


last pid: 21084;  load averages:  0.08,  0.03,  0.01     up 15+03:11:37  23:13:33
56 processes:  1 running, 54 sleeping, 1 stopped
CPU states:  3.5% user,  0.0% nice,  4.7% system,  1.2% interrupt, 90.7% idle
Mem: 365M Active, 430M Inact, 124M Wired, 48M Cache, 112M Buf, 37M Free
Swap: 4096M Total, 48K Used, 4096M Free

  PID USERNAME PRI NICE  SIZE    RES STATE    TIME   WCPU    CPU COMMAND
50627 root       2   0   143M   141M select  80:43  1.90%  1.90% XFree86
50670 pascal     2   0  7960K  5000K poll   100:08  1.86%  1.86% gkrellm
15182 pascal     2   0  6660K  5488K select   0:03  0.78%  0.78% Eterm
15164 pascal     2   0 15416K  9872K poll    34:27  0.05%  0.05% xmms
51005 pascal     2   0   126M   118M poll    20:16  0.00%  0.00% mozilla-bin
50675 pascal     2   0  2052K  1452K select   8:44  0.00%  0.00% wmmatrix
  208 root       2   0  3940K  2992K select   2:41  0.00%  0.00% cupsd
50674 pascal    10   0  2104K  1544K nanslp   2:04  0.00%  0.00% wmitime
50647 pascal     2   0  5484K  3996K select   1:51  0.00%  0.00% wmaker
15168 pascal    10   0  2344K  1684K nanslp   1:14  0.00%  0.00% wmmixer
20568 pascal     2   0 14992K 13912K poll     0:40  0.00%  0.00% xemacs-21.1.14
  312 nobody    10   0  2288K  1296K nanslp   0:29  0.00%  0.00% cups-polld
50727 pascal     2   0  2844K  2284K poll     0:16  0.00%  0.00% xscreensaver
  274 mysql      2  11 27016K  3632K poll     0:09  0.00%  0.00% mysqld
50721 pascal     2   0  1780K  1076K select   0:09  0.00%  0.00% root-tail
13123 pascal     2   0  6424K  4984K poll     0:08  0.00%  0.00% xdiary
  181 root       2   0  2204K   988K select   0:06  0.00%  0.00% master
50858 pascal     2   0  7032K  5772K select   0:06  0.00%  0.00% Eterm
52872 pascal     2   0  5564K  4312K select   0:05  0.00%  0.00% Eterm
   88 root       2   0   944K   556K select   0:04  0.00%  0.00% syslogd
   96 root      10   0   988K   480K nanslp   0:03  0.00%  0.00% cron
50713 pascal     2   0  3236K  1524K select   0:03  0.00%  0.00% fetchmail
  183 postfix    2   0  2260K  1052K select   0:03  0.00%  0.00% qmgr
50662 pascal     2   0  1944K  1240K select   0:02  0.00%  0.00% ssh-agent
16122 root       2   0 15036K  8456K select   0:02  0.00%  0.00% Xvfb
52911 pascal     2   0  1220K   760K select   0:01  0.00%  0.00% esd

2.9.2. Les signaux

Les signaux sont une forme limitée de communication inter-processus. Ils permettent de prévenir les processus de l'occurence de certains évènements. Il est possible d'envoyer des signaux à des processus interactifs à partir du clavier. La commande suivante permet de connaître les associations clés/signaux :


$ stty -a                                                                       
speed 38400 baud; 50 rows; 132 columns;
lflags: icanon isig iexten echo echoe echok echoke -echonl echoctl
        -echoprt -altwerase -noflsh -tostop -flusho pendin -nokerninfo          
        -extproc
iflags: -istrip icrnl -inlcr -igncr ixon -ixoff -ixany imaxbel -ignbrk
        brkint -inpck ignpar -parmrk
oflags: opost onlcr -ocrnl -oxtabs -onocr -onlret
cflags: cread cs8 -parenb -parodd -hupcl -clocal -cstopb -crtscts
        -dsrflow -dtrflow -mdmbuf
cchars: discard = ^O; dsusp = ^Y; eof = ^D; eol = <undef>;
        eol2 = <undef>; erase = ^?; erase2 = ^@; intr = ^C; kill = ^U;
        lnext = ^V; min = 1; quit = ^\; reprint = ^R; start = ^Q;
        status = ^T; stop = ^S; susp = ^Z; time = 0; werase = ^W;

Ainsi, la séquence <CTRL>-C (^C) permet d'envoyer le signal de terminaison (INT signal), la séquence <CTRL>-\ (^\) permet d'envoyer un autre signal de terminaison (QUIT), la séquence <CTRL>-Z (^Z) permet d'envoyer le signal de suspension (TSTP). Par défaut, les deux premiers signaux (INT et QUIT) termine le processus, tandis que le troisième ne fait que suspendre l'éxecution, i.e. elle peut donc être reprise. Ce comportement par défaut peut cependant être redéfini au sein d'un processus.

Sur une architecture 4.4BSD (FreeBSD, NetBSD, OpenBSD) on trouve 31 signaux. La commande, improprement nommée kill (man 1 kill) permet d'envoyer des signaux à un processus. Sa syntaxe est la suivante : kill <signal> <pus>, où <signal> est le signal envoyé au processus de numéro <pus>

La liste des signaux délivrable par la commande kill peut être obtenue de la manière suivante :


$ kill -l                                                                       
HUP INT QUIT ILL TRAP ABRT EMT FPE KILL BUS SEGV SYS PIPE ALRM TERM URG STOP     
TSTP CONT CHLD TTIN TTOU IO XCPU XFSZ VTALRM PROF WINCH INFO USR1 USR2 

Parmi ces signaux, deux ne peuvent être ni ignorés, ni détournés. Il s'agit du KILL (terminaison) et du STOP (suspension ou stop) (à ne pas confondre avec le TSTP vu précédemment).

2.9.3. Jobs

Cette notion inventée par la branche BSD d'Unix™ et introduite par csh est désormais disponible sur toutes les distributions Unixlibres.

Un job est soit un processus, soit un groupe de processus lancé par le shell. Un job peut être suspendu, redémarré, terminé, executé interactivement ou de manière asynchrone. Le shell sait gérer plusieurs jobs simultanément, toutefois à un instant donné seul un job peut avoir accès au terminal. Les jobs sont intéressants dès que les processus qu'ils contrôlent ont une durée de vie de quelques secondes. Analysons la séquence suivante :

$ su toor 1 
Password:
# id
uid=0(root) gid=0(wheel) groups=0(wheel)
# suspend 2 

Suspended
$ jobs 3
[1]  - Running                xemacs C-csh_n_tcsh.xml
[2]  + Suspended              su toor
$ du -s -h /usr & 4
[3] 21136
$ ls3.7G    /usr 5
[3]    Exit 1                 du -s -h /usr 6
$ ls /usr 
C-csh_n_tcsh.xml Makefile         _mystyle.xsl     images           my_style.xsl
CVS              _mystyle.css     html             my_print.dsl

$ stty tostop 7
$ du -s -h /usr &

...

$ jobs
[1]    Running                       xemacs C-csh_n_tcsh.xml
[2]  - Suspended                     su toor
[3]  + Suspended (tty output)        du -s -h /usr 8

$ %3 9
du -s -h /usr
3.7G    /usr

$ jobs
[1]  - Running                       xemacs C-csh_n_tcsh.xml
[2]  + Suspended                     su toor

$ %2
# exit 10
$ jobs
[1]  + Running                       xemacs C-csh_n_tcsh.xml

1

Changement d'identité utilisateur.

2

Suspension du processus et restauration de l'identité précédente.

3

Liste des jobs en cours;

4

Lancement d'une nouvelle commande, i.e. un processus de manière asynchrone, celui ci écrira son éventuel résultat sur la sortie standard, sans se préoccuper de ce qu'il peut se passer !

5

Le résultat de la commande du survient au moment où l'utilisateur tape sa commande ls et pertube donc son affichage.

6

Terminaison du processus. La commande ls s'affiche alors.

7

Pour éviter le mélange précédent, nous bloquons l'écriture du résultat de la commande sur le terminal.

9

Le comportement du processus change, l'utilisateur est informé (variable notify de csh, c.f. « Section 1.4, « Variables prédéfinies et d'environnement » ») que le job 3 est prêt à imprimer son résultat (il est suspendu jusqu'à ce qu'il soit autorisé à la faire).

8

On rappelle le job 3, ce qui lui permet d'afficher son résultat.

Un job asynchrone qui veut lire sur l'entrée standard alors que ce canal n'a pas été redirigé est toujours suspendu. Il faut le relancer de manière interactive pour qu'il puisse collecter ses données sur l'entrée standard.

10

On rappelle le job 2 et on le termine explicitement par un exit. Il reste alors un seul job en exécution asynchrone.

La liste des jobs en cours est donné par la commande jobs.

Le caractère % en première position dénote un job.

Le tableau suivant (c.f. « Tableau 5, « référencement des jobs » ») récapitule les différentes manières de référencer un job.

Tableau 5. référencement des jobs

ExpressionSémantique
%njob numéro n.
%strjob commençant par la chaine str.
%?strjob contenant la chaine str.

Le tableau suivant (c.f. « Tableau 6, « Commandes contrôlant les jobs » ») donne les commandes de contrôle d'un job.

Tableau 6. Commandes contrôlant les jobs

ExpressionSémantique
bg [name]

Place le job name en exécution asynchrone.

Si l'argument name n'est pas précisé, la commande s'applique au job courant.

name &Place le job name en exécution asynchrone.
fg [name]

Place le job name en exécution interactive.

Si l'argument name n'est pas précisé, la commande s'applique au job courant.

namePlace le job name en exécution interactive.
stop nameSuspend le job name.

Enfin, la commande kill permet aussi d'envoyer des signaux aux jobs, en utilisant le même référencement des jobs qu'en « Tableau 5, « référencement des jobs » ». Ainsi, la commande suivante met fin au job 1 :


$ kill -TERM %1                                                                 

Important

En csh, comme en tcsh les processus asynchrones ne sont pas affectés par un logout puisqu'il n'y a pas d'envoi du signal HUP à l'exécution du logout.

Corollaire : pas besoin de la commande nohup des autres shells (tel GNU/Bash).

2.9.4. limit

Cette commande a pour objet de définir des limites à la consommation des ressources du système par les processus. Il s'agit d'un intervalle définit par une borne haute (hard limits : qui ne peut être modifiée qu'à la baisse, sauf par le super-utilisateur et une borne basse (current limits : qui peut être accrue jusqu'aux valeurs de la borne haute).


$ limit         # affichage des limites courantes                               
cputime         unlimited
filesize        unlimited
datasize        262144 kbytes
stacksize       262144 kbytes
coredumpsize    0 kbytes
memoryuse       unlimited
vmemoryuse      unlimited
descriptors     2048 
memorylocked    unlimited
maxproc         1024 
sbsize  unlimited

$ limit coredumpsize 1024 # augmenter la limite basse d'un fichier core à 1024k 

$ limit maxproc 2048 # augmenter le nb max de proc concurrents
limit: maxproc: Can't set limit (Operation not permitted)

$ limit maxproc 512    # augmenter le nb max de proc concurrents (lim. cour.)
$ limit -h maxproc 784 # augmenter le nb max de proc concurrents (lim. hautes)

$ limit         # affichage des limites courantes                               
cputime         unlimited
filesize        unlimited
datasize        262144 kbytes
stacksize       262144 kbytes
coredumpsize    1024 kbytes
memoryuse       unlimited
vmemoryuse      unlimited
descriptors     2048 
memorylocked    unlimited
maxproc         512 
sbsize  unlimited

$limit -h       # affichage des limites hautes                               
cputime         unlimited
filesize        unlimited
datasize        262144 kbytes
stacksize       262144 kbytes
coredumpsize    unlimited
memoryuse       unlimited
vmemoryuse      unlimited
descriptors     2048 
memorylocked    unlimited
maxproc         784 
sbsize  unlimited

2.10. Redirection de commandes

Rapellons que, sous Unix™ en général et sous BSD en particulier, il existe trois canaux d'E/S standard :

  • L'entrée standard [stdin] associée au fd [file descriptor] 0 liée traditionnellement au clavier.

  • La sortie standard [stdout] associée au fd 1, liée traditionnellement à l'écran du terminal.

  • La sortie standard d'erreur [stderr] associée au fd 2, liée traditionnellement à l'écran du terminal.

Formellement, un descripteur de fichier est un entier non signé utilisé par les processus pour référencer les canaux d'E/S.

La puissance et la flexibilité du concept des canaux standards d'E/S tient essentiellement au fait que le shell peut rediriger ces canaux aussi bien sur des fichiers, que l'écran ou le clavier.

Tableau 7. Redirections

SymboleSémantique
> <fnom>La sortie standard est redirigée dans le fichier <fnom>. S'il existait, son contenu est perdu et sinon il est créé.
>> <fnom>La sortie standard est redirigée dans le fichier <fnom>, ouvert en mode ajout s'il existait, sinon il est créé.
>& <fnom>La sortie d'erreur est redirigée dans le fichier <fnom>. S'il existait, son contenu est perdu et sinon il est créé.
>>& <fnom>La sortie d'erreur est redirigée dans le fichier <fnom>, ouvert en mode ajout s'il existait, sinon il est créé.
< <fnom>L'entrée standard est le fichier <fnom>.
<< <mot>Lit les entrées du shell jusqu'à une ligne commençant (et contenant uniquement) le mot <mot> qui agit comme un marqueur de fin.

Le positionnement de la variable interne noclobber, permet d'éviter l'écrasement des fichiers existants dans le cas de l'utilisation des commandes de redirection > et >&. De plus les commandes >> et >>& ne peuvent être exécutées que sur des fichiers existants.

Enfin, la sémantique initiale des commandes de redirection (après activation de noclobber) peut être explicitement restituée en utilisant le symbole !. Ainsi, les commandes >!, >>!, >&! et >>&! ont un comportement identique à leurs homologues du tableau précédent (i.e. sans le !, c.f. « Tableau 7, « Redirections » »).

EXEMPLES :

$ cat > file.txt << fin_de_saisie                                               
>> première ligne
>> puis une 2e
>> Encore une autre !
>> C'est pas fini ...
>> fin_de_saisie

$  ll file.txt
-rw-------  1 pascal  gnu  - 65 Aug 1 15:58 file.txt

$ cat < file.txt  # équivalent à cat file.txt
première ligne
puis une 2e
Encore une autre !
C'est pas fini ...

$ ( find /home -name "*~" -print > fout ) >& ferr
                  # séparer les sorties standard (> fout) et d'erreur (>& ferr) 
$ cat fout        # les résultats
/home/pascal/enseignement/NeoTechIII/V2L-PRAI/CS2-csh/toto.sh~
/home/pascal/enseignement/NeoTechIII/V2L-PRAI/Progr-V2L/Progr-V2L.xml~
/home/miji/work/these/annexes/annexes.sxw~
/home/miji/work/these/partie1/part_legende/legendes.sxw~
/home/hosts/corto-home/turing/postfix/main.cf~
/home/hosts/corto-home/euler/ulocal-etc/flexbackup/flexbackup.conf~
/home/hosts/corto-home/euler/ulocal-etc/tripwire/twpol.txt~
/home/hosts/corto-home/euler/etc/ssh/sshd_config~
/home/hosts/corto-home/tux/etc/apache/httpd.conf~
/home/hosts/corto-home/tux/etc/apache-ssl/httpd.conf~

$ cat ferr        # les erreurs
find: /home/miji/.ssh: Permission denied
find: /home/miji/work/lit_reu/Dayot: Permission denied
find: /home/miji/Choices: Permission denied
find: /home/miji/pdf: Permission denied
find: /home/miji/tmp: Permission denied
find: /home/miji/.Eterm: Permission denied
find: /home/miji/.mozilla: Permission denied
find: /home/miji/.mutt: Permission denied
find: /home/miji/.netscape: Permission denied
find: /home/miji/.prefs: Permission denied
find: /home/miji/.vnc: Permission denied
find: /home/miji/.Gabber: Permission denied
find: /home/miji/.wmakerconf: Permission denied

2.11. Tubes [Pipelines]

Le mécanisme de pipeline consiste à rediriger la sortie d'une commande vers l'entrée d'une autre. D'un point de vue syntaxique nous avons la structure suivante :


<commandA> | <commandB>                                                         

Exemple 4. Utilisation du mécanisme de pipeline


$ ls -l | sort -k 5n                                                            

La sortie de la commande ls -l est redirigée vers l'entrée de la commande sort -k 5n.

Q :

Que permet de réaliser la commande précédente ?

R :

Enfin, en postfixant au tube ('|' ou encore pipe) l'ampersand (&), il est possible de combiner les sorties standard et d'erreur vers l'entrée de la commande qui suit (le tube).


<commandA> |& <commandB>                                                        

3. Structures de Contrôle & autres éléments algorithmiques

Ces structures algorithmiques sont utilisées dans les scripts shells. Pour rédiger un script shell (ici, en tcsh), il faut :

  1. Créer le fichier avec un éditeur de texte (sample.sh). La première ligne doit commencer avec le prologue [shebang] : #!/bin/tcsh.

  2. Lui attribuer la permission d'exécution sur le fichier créé (chmod +x sample.sh).

  3. Enfin, pour l'exécuter il suffit de taper le nom du fichier, puisque c'est désormais une nouvelle commande (si on est dans le répertoire courant de cette commande, il suffit de taper ./sample.sh).

Nous donnons dans ce qui suit, quelques exemples de scripts shells (csh).

3.1. Alternatives

3.1.1. La structure alternative if

Cette structure permet l'exécution conditionnelle d'une instruction. Voici sa syntaxe :


if ( <condition> ) then                                                         
  <liste instructions>
else if ( <condition> ) then
  <liste instructions>
else if ( <condition> ) then
  <liste instructions>
else
  <liste instructions>
endif

Exemple 5. Utilisation du if


#!/bin/csh
# /home/pascal/bin/fcomp.sh
#
# but : comparer deux fichiers
#
#                                      [Sept. 2002]   

if ( ${#argv} != 2 ) then
    echo "usage : $0 file1 file2"
    echo "compare deux fichiers file1 et file2 et dit s'ils sont identiques ou \
differents."
    exit -1
endif

cmp $argv[1] $argv[2] >& /dev/null
set ret = $?
if ( $ret == 0 ) then
    echo "Les fichiers $argv[1] et $argv[2] sont identiques."
else if ( $ret == 1 ) then
    echo "Les fichiers $argv[1] et $argv[2] sont differents."
else
    echo "Une erreur est survenue !"
endif
exit $ret

Exemple 6. Résultat du code de Exemple 5, « Utilisation du if »


$ ~/bin/fcomp.sh                                                                
usage : /home/pascal/bin/fcomp.sh file1 file2
compare deux fichiers file1 et file2 et dit s'il sont identiques ou differents. 

$ ~/bin/fcomp.sh ~/bin/fdate.sh ~/bin/fcomp.sh
Les fichiers /home/pascal/bin/fdate.sh et /home/pascal/bin/fcomp.sh sont differe
nts.

$ ~/bin/fcomp.sh ~/bin/fdate.sh /etc/shadow
Une erreur est survenue !

3.1.2. La structure alternative switch

Cette structure permet l'exécution conditionnelle d'une instruction.


switch ( <variable> )                                                           
  case motif1 :
         <liste instructions>
         breaksw

  case motif2 :
  case motif3 :
         <liste instructions>
         breaksw

  case motif4 :
         <liste instructions>

  case motif5 :
         <liste instructions>

  default:
         <liste instructions>

endsw

Exemple 7. Utilisation du switch

#!/bin/csh
# /home/pascal/bin/fdate.sh
#
# but :  conversion date en francais 
#
#                                      [Sept. 2002]

set res=`date`

# Traiter le jour                                                               
switch ( $res[1] )
    case Mon :
	set day=Lun
	breaksw
    case Tue :
	set day=Mar
	breaksw
    case Wed :
	set day=Mer
	breaksw
    case Thu :
	set day=Jeu
	breaksw
    case Fri :
	set day=Ven
	breaksw
    case Sat :
	set day=Sam
	breaksw
    case Sun :
	set day=Dim
	breaksw
endsw

# Traiter le mois
switch ( $res[2] )
    case Feb :
	set mon=Fev
	breaksw
    case Apr :
	set mon=Avr
	breaksw
    case May :
	set mon=Mai
	breaksw
    case Jun :
	set mon=Juin
	breaksw
    case Jul :
	set mon=Juil
	breaksw
    case Aug :
	set mon=Aou
	breaksw
    case Jan :
    case Sep :
    case Oct :
    case Nov :
    case Dec :
	set mon=$res[2]
	breaksw
endsw

# Afficher le resultat
echo "$day $res[3] $mon $res[6], $res[4] [$res[5]]"

Exemple 8. Résultat du code de Exemple 7, « Utilisation du switch »

$ fdate.sh                                                                      
Sam 12 Avr 2003, 21:20:45 [RET]

3.2. Boucles

3.2.1. Boucle while

Il s'agit de l'instruction standard qui permet d'exécuter le corps de la boucle tant que la condition d'entrée est vérifiée (valeur évaluée à vrai).


while ( <condition> )                                                           
  <corps_de_boucle>
end

Exemple 9. Utilisation du while


#!/bin/csh 
# ~/bin/test.sh                                                                 

set ind=1

while ( $ind < 11 )
  @ indcar = $ind * $ind
  echo $ind "  " $indcar
  @ ind++
end

Exemple 10. Résultat du code de Exemple 9, « Utilisation du while »


$ ~/bin/test.sh                                                                 
1     1                                                                         
2     4
3     9
4     16
5     25
6     36
7     49
8     64
9     81
10     100

3.2.2. Boucle repeat

Cette instruction permet de répéter un nombre entier de fois une même commande.


repeat <nombre_de_fois> <commande>                                              

Exemple 11. Utilisation et résultat du repeat


$ repeat 3 echo "hello, world !"                                                
hello, world !                                                                  
hello, world !
hello, world !

3.2.3. Boucle foreach

Cette instruction permet de traiter en séquence tous les éléments d'une liste.


foreach <variable> ( <liste_de_valeur> )                                        
  <corps_de_boucle>
end

Exemple 12. Utilisation du foreach


#!/bin/csh
# ~/bin/test.sh                                                                 

foreach i ( 1 2 3 4 5 6 7 8 9 )                                                 
  @ m = $i * 2
  echo -n " $m"
end
echo

Exemple 13. Résultat du code de Exemple 12, « Utilisation du foreach »


$ ~/bin/test.sh                                                                 
2 4 6 8 10 12 14 16 18                                                          
$

3.3. Variables utilisateurs

Ce sont les variables que les utilisateurs peuvent définir. Le shell étant un langage interprété non typé, aucune déclaration n'est nécessaire et la même variable peut contenir tour à tour une chaîne de caractères, un entier, ou un vecteur (tableau d'éléments de type chaîne de caractères ou entier, indexé par des entiers, commençant à 1).

Affectation. Cette opération permet d'associer un contenu à une variable (le contenant). En csh comme en tcsh, l'affectation se fait en utilisant la commande interne set de la manière suivante :

EXEMPLE :

$ set myvar1 = 10                                                               
$ set myvar2 = "chaine de caractère"
$ 

Accès au contenu. L'accès au contenu de la variable se fait en préfixant le nom de la variable par le symbole $.

EXEMPLE (SUITE) :

$ echo $myvar1                                                                  
10
$ echo $myvar2
chaine de caractère

$ echo myvar1     # omission du méta-caractère $
myvar1            # echo affiche le mot myvar1

On peut aussi encadrer la variable par les symboles { et } avant de la préfixer par le symbole $ :

EXEMPLE (SUITE) :

$ set si  = "pas "                                                              
$ echo "c'est vraiment $sidrôle"
sidrôle: Undefined variable.   # le $ porte ici sur le mot sidrôle et non sur si
$ echo "c'est vraiment ${si}drôle"
c'est vraiment pas drôle
$

Note

L'accès à une variable non définie produit (sauf rares exceptions) une erreur (en csh, comme en tcsh).

Effacer une variable. Cette opération permet de libérer la case mémoire occupée par la variable. Cela se fait en csh comme en tcsh, en utilisant la commande interne unset de la manière suivante :

EXEMPLE (SUITE) :

$ echo $myvar1                                                                  
10
$ unset myvar1
$ echo $myvar1
myvar1: Undefined variable.
$ 

Variable de type vecteur. Voici un exemple :

CODE :


#!/bin/csh
# ~/bin/testvect.sh

set vect = ( 2 -2 4 -4 6 -6 8 -8 10 -10 ) 

# afficher les elements du vecteur vect, element par element                    
set i = 1
set sum = 0
echo " -  Affichage element par element"
while ( $i <= ${#vect} )
    echo '$vect[' $i '] = ' $vect[$i]
    @ sum = $sum + $vect[$i]
    @ i++
end

echo " - Somme des elements = " $sum

# acc賠par tranche
set j = 5
echo "Voici le vecteur vect (${#vect} elements)         : " $vect[1-]
echo "Voici les $j premiers elements du vecteur    : " $vect[-$j]
echo "Voici les derniers elements ࠰artir du $j e : " $vect[$j-]

# fin du script


EXEMPLE :

$ ./testvect.sh                                                                 
 -  Affichage élément par élément
$vect[ 1 ] =  2
$vect[ 2 ] =  -2
$vect[ 3 ] =  4
$vect[ 4 ] =  -4
$vect[ 5 ] =  6
$vect[ 6 ] =  -6
$vect[ 7 ] =  8
$vect[ 8 ] =  -8
$vect[ 9 ] =  10
$vect[ 10 ] =  -10
 - Somme des elements =  0
Voici le vecteur vect (10 éléments)         :  2 -2 4 -4 6 -6 8 -8 10 -10
Voici les 5 premiers éléments du vecteur    :  2 -2 4 -4 6
Voici les derniers éléments à partir du 5 e :  6 -6 8 -8 10 -10

$

Modificateurs de variables. Les modificateurs [modifiers] suivants peuvent être appliqués aux variables. On travaillera avec l'exemple (un vecteur) suivant :


$ set mypath = ( /usr/local/src/foo.c /usr/src/bar.cc )   # un vecteur de path  

Tableau 8. Clé de modification

CléSémantiqueExemple
:h   :gh
interprète le contenu de la variable comme un nom de fichier Unixet en donne le début, i.e. la partie avant le dernier /

$ echo $mypath:h                    
/usr/local/src /usr/src/bar.cc
$ echo $mypath:gh
/usr/local/src /usr/src

:t   :gt
interprète le contenu de la variable comme un nom de fichier Unix™ et en donne la fin, i.e. la partie après le dernier /

$ echo $mypath:t                    
foo.c /usr/src/bar.cc
$ echo $mypath:gt
foo.c bar.cc

:r   :gr
supprime l'extension en fin de variable.

$ echo $mypath:r
/usr/local/src/foo /usr/src/bar.cc  
$ echo $mypath:gr
/usr/local/src/foo /usr/src/bar

:e   :ge
donne l'extension correspondant à la fin de variable.

$ echo $mypath:e                    
c /usr/src/bar.cc
$ echo $mypath:ge
c cc

:q   :gq
quote la variable pour éviter tout mécanisme de substitution. 
:x   :gx
idem précédent, mais cassure en mots sur les caractères : blanc, espace et nouvelle ligne.
 

Mécanismes de substitution. 

Tableau 9. Clé de substitution

CléSémantique
$?<name> = ${?<name>}Renvoit 1 si la variable est définie, 0 sinon.
$?0Renvoit 1 si $0 est définie, 0 sinon.
$$Substituée par le pid du shell parent.
$!Substituée par le pid du dernier processus asynchrone lancé par le shell parent.
$<Substituée par une ligne de l'entrée standard.


$ set v = toto
$ echo ${?v}   # renvoit 1 puisque la variable v est définie        
1
$ echo $u
u: Undefined variable.
$ echo ${?u}   # moyen commode pour savoir si une variable est définie          
0 

3.4. Paramètres du shell

Le shell définit pour chaque commande un certain nombre de paramètres « automatiques ».

Tableau 10. Opérateurs de comparaison

Paramètre(s)Utilisation
$0nom de la commande ou du script invoqué.
$1, $2 .. $n   ${1}, ${2} .. ${n}encore équivalent à $argv[1], $argv[2], .. $argv[n]    valeurs des paramètres positionnels passés à la commande ou au script.
$* = $argv[*]     = ${argv[*]}ensemble des paramètres, sauf $0.
$# = $#argv      = ${#argv}nombre de paramètres effectifs, $0 non compris.

CODE :

#!/bin/csh
# ~/bin/testparm.sh

echo 'je suis le script, $0 = ' $0

if ( ${#argv} > 0 ) then
    echo ' évoqué avec $# (= $#argv = ${#argv}) = ' ${#argv}  ' arguments sur la
 ligne de commande'
    echo 'Voici les paramètres : $* (= $argv[*] = ${argv[*]}) = ' ${argv[*]}
    set i = 1
    foreach param ( $argv[*] ) 
       écho "paramètres ($i) :  $param"
       @ i++
    end
else
    echo ' pas d arguments, nb arg $# (= $#argv = ${#argv}) = ' ${#argv}
endif

# fin du script


EXEMPLE :

$ ./testparam.sh toto titi tutu 147
je suis le script, $0 =  ./testparam.sh
 évoqué avec $# (= $#argv = ${#argv}) =  4  arguments sur la ligne de commande  
Voici les paramètres : $* (= $argv[*]) =  toto titi tutu 147
paramètre (1) :  toto
paramètre (2) :  titi
paramètre (3) :  tutu
paramètre (4) :  147
$
$ ./testparam.sh
je suis le script, $0 =  ./testparam.sh
 pas d arguments, nb arg $# (= $#argv = ${#argv}) =  0
$

3.5. Lecture sur l'entrée standard

Elle se fait en utilisant la variable spéciale $<

CODE :

#!/bin/csh
# ~/bin/testread.sh                                                             

echo -n " Votre réponse (o, n) ? "
set rep = $<

if ( $rep == o ) then 
   echo "réponse oui"
else
   echo autre réponse : $rep
endif


EXEMPLE :

$ ./testread.sh
Votre réponse (o, n) ? yes
autre réponse : yes

$ ./testread.sh
 Votre réponse (o, n) ? o
réponse oui

3.6. Expressions conditionnelles

Règles :

  • Les expressions utilisent les mêmes opérateurs que le langage C (sémantique identique (sauf marque : (¢), c.f. « Tableau 11, « Opérateurs de comparaison » »)). On retrouve les instructions if, while, @ et exit,

  • Les chaines numériques commençant par un 0 sont interprétées comme des valeurs en base octale,

  • Le résultat de toute expression est une chaîne représentant un nombre décimal.

  • La valeur 0 s'interprète en contexte logique comme la valeur « faux », toutes les autres ont la valeur « vrai ».

Tableau 11. Opérateurs de comparaison

OpérateurSémantique
O P E R A T E U R S    D E    F I C H I E R S
-d <filename>(¢) est vraie si le fichier désigné par <filename> est un répertoire.
-e <filename>(¢) est vraie si le fichier désigné par <filename> existe.
-f <filename>(¢) est vraie si le fichier désigné par <filename> est un fichier régulier.
-o <filename>(¢) est vraie si le fichier désigné par <filename> est propriété de l'utilisateur.
-r <filename>(¢) est vraie si le fichier désigné par <filename> est un fichier accessible en lecture.
-w <filename>(¢) est vraie si le fichier désigné par <filename> est un fichier accessible en écriture.
-x <filename>(¢) est vraie si le fichier désigné par <filename> est un fichier exécutable.
-z <filename>(¢) est vraie si le fichier désigné par <filename> est de taille nulle.
-b <filename>[tcsh] (¢) est vraie si le fichier désigné par <filename> est un fichier spécial en mode bloc.
-c <filename>[tcsh] (¢) est vraie si le fichier désigné par <filename> est un fichier spécial en mode caractère.
-l <filename>[tcsh] (¢) est vraie si le fichier désigné par <filename> est un lien symbolique.
-p <filename>[tcsh] (¢) est vraie si le fichier désigné par <filename> est un tube nommés (FIFO).
-S <filename>[tcsh] (¢)est vraie si le fichier désigné par <filename> est un socket.
C O M P A R A I S O N    D E    C H A I N E S
<str1> == <str2>est vraie si <str1> est égale à <str2>.
<str1> != <str2>est vraie si <str1> est différente de <str2>.
<str1> =~ <str2>(¢) est vraie si le motif <str2> (right hand side) correspond au motif <str1>.
<str1> !~ <str2>(¢) est vraie si le motif <str2> (right hand side) ne correspond pas au motif <str1>.
C O M P A R A I S O N    D ' E N T I E R S
<int1> >= <int2>est vraie si <int1> est supérieur ou égal à <int2>.
<int1> > <int2>est vraie si <int1> est strictement supérieur à <int2>.
<int1> <= <int2>est vraie si <int1> est inférieur ou égal à <int2>.
<int1> < <int2>est vraie si <int1> est strictement inférieur à <int2>.
C O M B I N A I S O N    D ' E X P R E S S I O N S
( <expr> ) est vraie si <expr> est vraie.
! <expr> est vraie si <expr> est fausse.
<expr1> && <expr2> est vraie si <expr1> et <expr2> sont simultanément vraies.
<expr1> || <expr2> est vraie si <expr1> ou <expr2> est/sont vraie(s).

Tableau 12. Opérateurs (par ordre décroissant de priorité)

OpérateursSémantique
(   )regroupement
~complément bit à bit
!négation logique.
*   /   %multiplication, division, modulo
+   -addition, soustraction
<<   >>décalage à gauche, décalage à droite
<=   <   >=   >opérateurs relationnels
==   !=   =~   !~opérateurs de comparaisons de chaînes
&« et » bit à bit
^« ou exclusif » bit à bit
|« ou » (inclusif) bit à bit
&&« et » logique
||« ou » logique

La commande interne @ permet de réaliser des opérations arithmétiques sur des valeurs ou variables entières, attention à respecter l'espace entre le symbole @ et la variable.


$ set v = 3
$ set u = 8
$ set p = 5
$ @ x = $v + $u * $p   # attention à la priorité des opérateurs                 
$ echo $x
43
$ @ x = ( $v + $u ) * $p
55

$ @ q = $u / $p        # division entière
$ @ r = $u % $p
$ echo quotient = $q et reste = $r
quotient = 1 et reste = 3

$ @ v++                # incrémentation d'une unité
$ echo $v
4

$ @ v += 2             # incrémentation de deux unités
$ echo $v
6

$ @ u /= 2             # @ u = u / 2
$ echo $u
4

$ @ u = ( $u <<  3 )   # décalage à gauche de 3 bits, ce qui revient à une x 8  
$ echo $u
32

$ @ v = (( $v + 4 ) >> 2 ) # 10 décaler de 2 bits à droite, soit 10 / 4 = 2
$ echo $v
2


4. Les apports de TCsh

4.1. Completion étendue

Sous tcsh le mécanisme de completion des noms a été amélioré. Ce shell peut compléter les noms des fichiers, des commandes et des variables. De plus la completion des noms de fichiers est programmable !

La completion est déclenchable par la touche <TAB>, bien que par compatibilité ascendante avec csh, la touche <ESC> reste opérationnelle.

Contexte de variables : Il faut utiliser le préfixe $ (il change le contexte de la completion) :


$ set varia_1=10                                                                
$ echo $var<TAB>
$ echo $varia_1 <ENTREE>
10

4.2. bindkey

Cette commande permet l'édition des commandes en ligne dans un buffer au moyen des contrôles associés aux éditeurs classiques d'Unix, à savoir vi ou emacs. Utilisée seule, elle retourne la liste des associations clés/commandes.

Le positionnement par défaut est souvent le mode emacs, il est déterminé à la compilation. La variable version permet de connaître la version de la commande ainsi que les options de compilation. Dans l'exemple suivant, l'absence de la clé vi, permet d'affirmer que le mode par défaut est emacs.


$ echo $version
tcsh 6.12.00 (Astron) 2002-07-23 (i386-intel-FreeBSD) options 8b,nls,dl,al,kan,s
m,rh,color,dspm,filec

Cette commande permet aussi de commuter entre le mode vi et le mode emacs.


$ bindkey -e   # mode emacs                                                     
$ bindkey -v   # mode vi

Dans le tableau suivant, nous présentons un sous-ensemble des commandes d'édition :

Tableau 13. Quelques couples clé/commande en mode emacs

CléCommande
^APositionne le curseur en début de ligne
^BRecule horizontalement le curseur d'un caractère
^EPostionne le curseur en fin de ligne
^LEfface l'ecran
^KCoupe tous les caractères à la droite du curseur
^TTransposition de caractères
^MNouvelle ligne
^UEfface toute la ligne
^CSignal d'interruption
^ZSignal de suspension
BackspaceEfface le premier caractère situé à gauche du curseur
Flèche gaucheDéplacement d'un caractère à gauche du curseur
Flèche droiteDéplacement d'un caractère situé à droite du curseur
Flèche hautRemonte dans l'historique des commandes (vers les commandes les plus anciennes)
Flèche basDescend dans l'historique des commandes

4.3. Spelling Correction

Ce mécanisme est déclenché en postionnant la variable (interne) tcsh correct (valeurs possibles cmd ou all) :


$ set correct = cmd
$ lzss test.csh                          # ooops typo !

CORRECT>less test.csh  (y|n|e|a)? yes    # frappe de la touche y ou <ESPACE>    
#!/bin/csh                               # lecture et affichage du fichier

echo '\nJe suis le programme $0   : ' $0
...

5. Exercices

Exercice - Mécanisme d'évaluation (1)

Soit les affectations suivantes :


$ set x=date                                                                        
$ set y=foobar 

Tester les commandes suivantes et expliquer dans chaque cas le résultat obtenu.


$ echo $x ; echo $y ; echo $z                                                   

$ echo "$x" ; echo "$y" ; echo "$z"

$ echo '$x' ; echo '$y' ; echo '$z'

$ echo `$x` ; echo `$y` ; echo `$z` 

$ $x ; $y ; $z

$ "$x" ; "$y" ; "$z"

$ '$x' ; '$y' ; '$z'

$ `$x` ;  `$y` ; `$z` 

$ $y=`$x` 

$ echo $foobar

Exercice - Mécanisme d'évaluation (2)

Tester les commandes suivantes et expliquer dans chaque cas le résultat obtenu.


$ echo pwd                                                                      

$ `echo pwd`

$ 'echo pwd'

$ "echo pwd"

$ echo echo pwd

$ echo `echo pwd`

$ echo 'echo pwd'

$ echo "echo pwd"

$ echo '`echo pwd`'

$ echo '`echo pwd`'

Exercice - Modification de l'environnement d'un processus, incidence sur le/les fils

Dans un terminal, sous le shell courant définir deux variables (var1 et var2) et modifier quelques variables d'environnement. Afficher l'environnement ainsi modifié.

Dans ce même terminal, empiler un nouveau shell (/bin/tcsh). Quelle sont les valeurs de var1 et var2, des variables d'environnement ? Définir une variable var3.

Quitter ce shell et revenir à l'environnement initial (exit). Examiner son environnement, que vaut var3 ? Conclure.

Exporter maintenant la variable var1, empiler un nouveau shell. Examiner son environnment. Modifier ensuite var1. Définir la variable var2. Quitter ce shell, pour revenir à celui de départ. Quelles sont les valeurs de var1 et var2 ?

Et si avant de quitter ce shell empilé, vous aviez exporté la variable var2, qu'auriez-vous obtenu ?

Exercice - Exécution asynchrone concurrente de processus

Exécuter la commande suivante dans un premier terminal, et dans un second ouvert pour l'occasion, lister les processus en cours d'exécution (se limiter aux seuls processus du terminal « générateur »), observer leur filiation, le nombre de processus :


$ ( ls -la /usr/bin/ ; sleep 5 ; echo "5 - OK" ; last ) & \                     
( cat /etc/passwd ; sleep 7 ; echo "7 - OK" ; cat /etc/group ) & ps aux

Observer l'entrelacement des résulats de ces commandes.

La séquence backslash (i.e. \), suivit de la touche <Entrée> indique au shell une continuation de la commande sur la ligne suivante. Que fait la commande sleep ?

Exercice - Manipulation de jobs (1)

Lancer la commande suivante : find / -type d -print, laquelle recherche tous les objets de type répertoire dans toute l'arborescence. La recherche se fait de manière récursive et comme l'arborescence est grande, l'exécution est un peu longue. On est bloqué tant que le processus exécutant le find n'est pas terminé. Il vous est demandé de :

  1. suspendre (ou stopper) le processus.

  2. de le relancer en arrière-plan

  3. de le ramener au premier plan

  4. de le terminer.

Est-il possible de « tuer » des processus ne vous appartenant pas ? Tester-le.

Si vous n'êtes pas assez rapide ou bien si la commande s'exécute trop rapidement, ouvrir un nouveau terminal et refaire le travail demandé.

Exercice - Manipulation de jobs (2)

Reprendre l'exemple de la commande find, de la section « Section 2.10, « Redirection de commandes » », mais limiter la recherche au répertoire /etc.

  1. Rediriger uniquement la sortie d'erreur dans le fichier (ferr) ;

  2. Rediriger uniquement la sortie standard dans un fichier (fout) ;

  3. Multiplexer les sorties standard et d'erreur dans le même fichier (fouterr) ;

  4. Rediriger (démultiplexer) la sortie standard et la sortie d'erreur dans les fichiers respectifs (fout et ferr).

Références

[0] OpenBSD man pages. csh. man csh. Janvier 1994.

[1] Heuer Konrad. Making friends with C-Shell and TC-shell, Part I. http://ezine.daemonnews.org/200112/. Décembre 2001.

[2] Heuer Konrad. Making friends with C-Shell and TC-shell, Part II. http://ezine.daemonnews.org/200201/. Janvier 2002.

[3] Heuer Konrad. Making friends with C-Shell and TC-shell, Part III. http://ezine.daemonnews.org/200202/. Février 2002.

[4] University of Hawaii at Manoa - College of Engineering. The C Shell tutorial. csh tutorial. 2001.

[5] Pélissier Christian. Unix. Utilisation, Administration, Réseau Internet. Chap 9, pp 163-176. HERMES. 1992, 1995, 1996, 1998. isdn : 2-86601-707-2.