- Chapitre 1) Introduction
- Chapitre 2) Notions de base en shell
- 2.1) Rappel sur l'entrée en session
- 2.2) Étude des différents fichiers de démarrage
- 2.3) Variables et environnement
- 2.4) Notion d'environnement : instruction export
- 2.5) Quelques variables système
- 2.6) Compléments sur les variables
- 2.7) Initialisation de variables
- 2.8) Caractères spéciaux
- 2.9) Structure et exécution d'un script shell
- 2.10) Commentaire et shell interpréteur d'un script
- 2.11) Code retour et traitement associé
- 2.12) Interprétation d'une ligne de commande
- 2.13) Paramètres du script
- Chapitre 3) Programmation shell
- Chapitre 4) Utilitaire et commandes Unix
- Chapitre 5) sed & awk
Chapitre 1: Introduction
Objectifs:- Rappels sur les principes d'un système d'exploitation
- Rappels sur certaines commandes de base
- Rappel sur l'utilisation du manuel
1.1) Principes fondamentaux de la programmation shell
Principes fondamentaux:- Utilisation en système d'exploitation multi-tâche
- Complexe et puissant
- Nombreuses applications intégrées
- Grande collaboration avec le "Domaine Public"
Ce document comporte, en tant que tel, relativement peu d'exemples car il sera accompagné, par ailleurs, d'un nombre important d'exercices de mise-en-oeuvre.
On ne fera plus forcément la distinction entre le traditionnel "Bourne-shell" et les extensions apportées par le "Korn-shell" car on suppose que celui-ci est largement standardisé aujourd'hui et que son utilisation, dans le cadre de scripts d'entreprise, est tout à fait "dans les moeurs".
1.2) Documentation disponible
Documentation: Utilisation en système d'exploitation multi-tâche
Complexe et puissant
Nombreuses applications intégrées
Grande collaboration avec le "Domaine Public"
1.2.1) Site Internet
1.2.2) Livres
The New KornShell Command and Programming Language (Morris Bolksy & David Korn , Prentice Hall, 1995)
Learning the KornShell (Bill Rosenblatt , O'Reilly & Ass~ 1993 au format électronique)
Korn Shell Programming Tutorial (Barry Rosenberg , Addison- Wesley, 1991)
Langages de scripts sous Linux (Blaess, Eyrolles, 12/2001 )
La programmation sous Unix 3ème éd (JM Rifflet)
Chapitre 2: Notions de base en shell
Objectifs: Rappels sur l'entrée en session
Fichiers de démarrage
2.1) Rappel sur l'entrée en session
Entrée en session: Mode commande
Interface Graphique: CDE, Gnome, KDE
2.2) Étude des différents fichiers de démarrage
Fichiers de démarrage: Entrée en session
Démarrage d'un nouveau processus
Fin de session
Shell: interpréteur de commandes
Shell: langage de programmation
Une connexion consiste en un processus correspondant à l'exécution d'un shell. Ce shell est celui choisi par l'administrateur lors de la création du compte. L'utilisateur peut demander à l'administrateur de changer de shell.
Ce shell est à la fois un interpréteur de commandes et un langage de programmation permettant l'écriture de procédures utilitaires et constituant un des outils de travail de l'administrateur.
Les shells essentiels du monde UNIX sont, dans l'ordre chronologique:
Bourne-shell (natif, est de base /bin/sh administrateur UNIX)
C-shell
Korn-shell ( /bin/ksh utilisateur UNIX)
Posix Shell ( version normalisée du Korn-Shell retenue par l'organisme X/Open)
Bash ( pour Bourne Again Shell : le shell de Linux ) /bin/bash deviendra à terme le shell UNIX
tcsh
Z-shell
Dans la suite, les références au shell sont celles des environnements Korn-shell bien standardisés aujourd'hui.
2.3) Variables et environnement
La notion de variable concerne surtout l'aspect programmation. Cependant, il existe un certain nombre de variables système prédéfinies ayant un rôle important vis à vis de l'utilisateur interactif.
Une variable shell contient une chaîne de caractères quelconque. Son nom peut être constitué de lettres, de chiffres et du caractère _ (souligné) , il ne peut pas commencer par un chiffre (conventions des identificateurs du langage C).
Le caractère = (signe égal) est le symbole d'affectation de variable.
Le caractère $ permet de désigner la valeur d'une variable.
La commande unset permet d'annuler la définition d'une variable:
prabou@prabou-VPCZ23C5E:~$ mavariable=ambre prabou@prabou-VPCZ23C5E:~$ echo $mavariable ambre prabou@prabou-VPCZ23C5E:~$ unset mavariable prabou@prabou-VPCZ23C5E:~$ echo $mavariable prabou@prabou-VPCZ23C5E:~$
Par conventions:
-les variables locales sont en minuscules (uniquement dans le shell)
-les variables globales sont en majuscules (shell et sous-shells)
On peut donc créer deux variables différentes "toto" et "TOTO" qui sont bien différentes, d'où l'importance de prendre des noms différents.
var=valeur et ensuite pour la rendre globale il faut exporter cette variable avec export var
On peut aussi le faire en une seule commande avec export VAR=valeur
2.4) Notion d'environnement : instruction export
L'environnement shell (variables exportées) est constitué de l'ensemble des variables qui sont transmises à un processus" fils" par le mécanisme de "fork".
Une variable non exportée n'est pas connue dans le processus fils. Les modifications, dans les processus fils, des variables exportées s'opèrent sur des copies locales et n'altèrent donc en rien les valeurs des variables dans le processus "parent".
2.4.1) Liste des variables
Afficher la liste de toutes les variables, celles de l'environnement et celles qui ne s'y trouvent pas.
$ set | more
LANG=C
PATH=/usr/bin:/usr/bin/X11
EDITOR=/usr/bin/vi
...
LANG=C
PATH=/usr/bin:/usr/bin/X11
EDITOR=/usr/bin/vi
...
2.4.2) Afficher la liste des variables d'environnement
prabou@prabou-VPCZ23C5E:~$ env | more SHELL=/bin/bash SESSION_MANAGER=local/prabou-VPCZ23C5E:@/tmp/.ICE-unix/1335,unix/prabou-VPCZ23C5E:/tmp/.ICE-unix/1335 WINDOWID=29360135 QT_ACCESSIBILITY=1 COLORTERM=truecolor XDG_CONFIG_DIRS=/etc/xdg/xdg-plasma:/etc/xdg:/usr/share/kubuntu-default-settings/kf5-settings XDG_SESSION_PATH=/org/freedesktop/DisplayManager/Session1 LANGUAGE=fr MANDATORY_PATH=/usr/share/gconf/plasma.mandatory.path SSH_AUTH_SOCK=/tmp/ssh-lTaDZUjJQ7vy/agent.1216 SHELL_SESSION_ID=cd276a176dc844ed8af12184e843d95c DESKTOP_SESSION=plasma LC_MONETARY=fr_FR.UTF-8 SSH_AGENT_PID=1274 GTK_RC_FILES=/etc/gtk/gtkrc:/home/prabou/.gtkrc:/home/prabou/.config/gtkrc XDG_SEAT=seat0 PWD=/home/prabou XDG_SESSION_DESKTOP=KDE LOGNAME=prabou XDG_SESSION_TYPE=x11 GPG_AGENT_INFO=/run/user/1000/gnupg/S.gpg-agent:0:1 XAUTHORITY=/tmp/xauth-1000-_0 GTK2_RC_FILES=/etc/gtk-2.0/gtkrc:/home/prabou/.gtkrc-2.0:/home/prabou/.config/gtkrc-2.0 HOME=/home/prabou LANG=fr_FR.UTF-8 LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz= 01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.zst=01;31:*.tzst=01;31:*.bz2=0 1;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.wim= 01;31:*.swm=01;31:*.dwm=01;31:*.esd=01;31:*.jpg=01;35:*.jpeg=01;35:*.mjpg=01;35:*.mjpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;3 5:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.as f=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.m 4a=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.oga=00;36:*.opus=00;36:*.spx=00;36:*.xspf=00;36: XDG_CURRENT_DESKTOP=KDE KONSOLE_DBUS_SERVICE=:1.100 KONSOLE_DBUS_SESSION=/Sessions/1 PROFILEHOME= TMPDIR=/tmp XDG_SEAT_PATH=/org/freedesktop/DisplayManager/Seat0 KONSOLE_VERSION=181203 KDE_SESSION_UID=1000 LESSCLOSE=/usr/bin/lesspipe %s %s XDG_SESSION_CLASS=user TERM=xterm-256color DEFAULTS_PATH=/usr/share/gconf/plasma.default.path LESSOPEN=| /usr/bin/lesspipe %s USER=prabou COLORFGBG=15;0 KDE_SESSION_VERSION=5 PAM_KWALLET5_LOGIN=/run/user/1000/kwallet5.socket DISPLAY=:0 SHLVL=0 LC_MEASUREMENT=fr_FR.UTF-8 XDG_VTNR=1 XDG_SESSION_ID=3 GS_LIB=/home/prabou/.fonts XDG_RUNTIME_DIR=/run/user/1000 LC_TIME=fr_FR.UTF-8 QT_AUTO_SCREEN_SCALE_FACTOR=0 LC_COLLATE=fr_FR.UTF-8 XCURSOR_THEME=breeze_cursors XDG_DATA_DIRS=/usr/share/plasma:/usr/local/share:/usr/share:/var/lib/snapd/desktop KDE_FULL_SESSION=true PATH=/home/prabou/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin KONSOLE_PROFILE_NAME=Par défaut DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus LC_NUMERIC=fr_FR.UTF-8 KONSOLE_DBUS_WINDOW=/Windows/1 _=/usr/bin/env prabou@prabou-VPCZ23C5E:~$
Déclarer une variable d'environnement:
prabou@prabou-VPCZ23C5E:~$ env | grep variable prabou@prabou-VPCZ23C5E:~$ variable=valeur prabou@prabou-VPCZ23C5E:~$ export variable prabou@prabou-VPCZ23C5E:~$ env | grep variable variable=valeur prabou@prabou-VPCZ23C5E:~$
Note: Avec le ksh la syntaxe directe export variable=valeur est possible.
2.5) Quelques variables système
Certaines variables ont un rôle plus ou moins important pour l'utilisateur du shell.
Ces variables système peuvent avoir une valeur par défaut ou être initialisées à diverses étapes de la procédure de connexion. A ce niveau, l'administrateur doit décharger au maximum le travail de l'utilisateur.
Variable | Description |
---|---|
PATH | Liste des noms de répertoires dans lesquels le système cherche les commandes. |
PS1 | Prompt principal ($ par défaut). |
PS2 | Prompt secondaire (> par défaut). Le prompt secondaire apparaît si la commande doit se continuer sur la ligne suivante. |
TERM | Type du terminal (émulation). Une bonne valeur est nécessaire notamment au bon fonctionnement de vi |
EDITOR | Editeur indirect utilisé par certains utilitaires nécessitant une édition. |
HOME | Nom complet du répertoire de connexion. |
LOGNAME | Nom de connexion |
PWD | Nom du répertoire courant. Cette variable est tenue à jour par la commande cd |
OLDPWD | Nom du répertoire courant précédent (on peut utiliser la commande cd - pour y retourner; spécifique au ksh) |
PPID | Valeur du PID du processus père (spécifique au ksh) |
TMOUT | Nombre de secondes d'inactivité, sous le prompt du shell, avant déconnexion (TMOUT=0 - pas de déconnexion; spécifique au ksh) |
Autres variables utiles gérées par le shell:
Variable | Description |
---|---|
$ | PID du shell interpréteur |
! | PID du dernier fils lancé en arrière-plan |
? | Code de retour de la dernière commande appelée |
2.5.1) Exemples d'utilisation
Avoir comme prompt principal le nom du répertoire courant:
$ PS1='$PWD $ '
/home/stagel $ cd ..
/home $ cd
/home/stagel $ cd ..
/home $ cd
Redéfinir le prompt secondaire:
$ PS2='suite : '
echo "bonjour cher
suite : ami"
bonjour cher
ami
echo "bonjour cher
suite : ami"
bonjour cher
ami
Gérer le PATH et le mettre à jour si besoin:
$ echo $PATH
/usr/bin:/usr/bin/X11
$ mount
ksh : mount : not found
$ /usr/sbin/mount
/ on /dev/root read/write/setuid on Nov 25 16 :03 :29
/stand on /dev/dsk/c0t0d0sa read/write on Nov 25 16 :03 :30
/home on /dev/dsk/c0t0d0s4 read/write/setuid on Nov 25
16 :03 :43
...
$ PATH=$PATH:/usr/sbin
$ echo $PATH
/usr/bin:/usr/bin/X11:/usr/sbin
$ mount
/ on /dev/root read/write/setuid on Nov 25 16 :03 :29
/stand on /dev/dsk/c0t0d0sa read/write on Nov 25 16 :03 :30
/home on /dev/dsk/c0t0d0s4 read/write/setuid on Nov 25
16 : 03 :43
/usr/bin:/usr/bin/X11
$ mount
ksh : mount : not found
$ /usr/sbin/mount
/ on /dev/root read/write/setuid on Nov 25 16 :03 :29
/stand on /dev/dsk/c0t0d0sa read/write on Nov 25 16 :03 :30
/home on /dev/dsk/c0t0d0s4 read/write/setuid on Nov 25
16 :03 :43
...
$ PATH=$PATH:/usr/sbin
$ echo $PATH
/usr/bin:/usr/bin/X11:/usr/sbin
$ mount
/ on /dev/root read/write/setuid on Nov 25 16 :03 :29
/stand on /dev/dsk/c0t0d0sa read/write on Nov 25 16 :03 :30
/home on /dev/dsk/c0t0d0s4 read/write/setuid on Nov 25
16 : 03 :43
Annuler la définition de la variable TERM:
$ unset TERM
$ vi
Visual needs addressable cursor or upline capability
:q
$ TERM=bidon; export TERM
$ vi
bidon : Unknown terminal type
Visual needs addressable cursor or upline capability
:q
$ TERM=vt100
$ export TERM
$ vi
Visual needs addressable cursor or upline capability
:q
$ TERM=bidon; export TERM
$ vi
bidon : Unknown terminal type
Visual needs addressable cursor or upline capability
:q
$ TERM=vt100
$ export TERM
2.6) Compléments sur les variables
On sait que la valeur d'une variable est donnée par le symbole $. Des notations complémentaires sont disponibles pour permettre de lever des ambiguïtés syntaxiques, et récupérer la taille des variables.${var} permet d'opérer correctement des concaténations:
prabou@prabou-VPCZ23C5E:~$ nom=ambre prabou@prabou-VPCZ23C5E:~$ var=systems prabou@prabou-VPCZ23C5E:~$ echo $nom ambre prabou@prabou-VPCZ23C5E:~$ echo $var systems prabou@prabou-VPCZ23C5E:~$ echo $nom_$var systems prabou@prabou-VPCZ23C5E:~$ echo ${nom}_$var ambre_systems prabou@prabou-VPCZ23C5E:~$
${#var} permet d'obtenir la longueur d'une variable:
prabou@prabou-VPCZ23C5E:~$ echo $HOME /home/prabou prabou@prabou-VPCZ23C5E:~$ echo ${#HOME} 12 prabou@prabou-VPCZ23C5E:~$
2.7) Initialisation de variables
varlen=${#var}                     longueur d'une variable
var=${varl:-value}                     var=var1 si var1 est positionné, var=value si var1 n'est pas positionnée ou vide
var=${var1:=var2}                     var= $var1 si var1 est positionné et non vide, sinon = $var2
var=${varl=var2}                     var=$var1 si var1 est positionné, même s'il est vide, sinon = $var2
var=${varl:+var2}                     var=$var2 si varl est positionné et non vide, sinon var n'est pas positionné
var=${var1:+var2}                     var=$var2 si var1 est positionné même s'il est vide, sinon var n'est pas positionnée
var=${varl: ?}                     var=varl si varl est positionnée, sinon, on a un message d'erreur
var=${var1: ?var2}                     var=var1 si var1 est positionnée, sinon var=var2 et quitte
2.8) Caractères spéciaux
Une des premières fonctions du shell est d'interpréter un certain nombre de caractères avant l'appel des commandes. Il est à noter que les commandes Unix ne traitent pas les caractères spéciaux.Elles héritent d'une liste de paramètres déjà résolue et ne se préoccupent pas de mécanismes comme les redirections ou le "pipeline". Ce principe de base favorise grandement l'activité de programmation et s'inscrit parfaitement dans la démarche "boîte à outils" modulaire voulue par les concepteurs du système.
Rappel des caractères déjà évoqués:
Caractère | Description |
---|---|
< | Redirection de l'entrée standard |
> et >> | Redirections de la sortie standard |
2> et 2>> | Redirections de l'erreur standard |
; | Processus séquentiels |
| | Mécanisme du "pipeline" |
& | Mode arrière-plan |
( ) | Grouper des commandes |
= | Affectation de variable |
$ | Contenu d'une variable |
Expressions génériques simples:
Caractère | Description |
---|---|
* | N'importe quelle chaîne dans un nom de fichier Utilisé seul, signifie : "Tous les fichiers du répertoire courant" (ne sélectionne pas les fichiers commençant par . (point)) |
? | Présence d'un caractère quelconque dans un nom de fichier |
[ensemble_de_caractères] | Présence d'un caractère de l'ensemble |
[!ensemble_de_caractères] | Présence d'un caractère ne figurant pas dans l'ensemble |
Exemple:
$ touch fic1 fic2 essai99 fic.txt exemple
$ echo *
fic1 fic2 essai99 essai99 fic.txt exemple
$
$ echo .[!.]*
.profile
. sh_history
$ echo *
fic1 fic2 essai99 essai99 fic.txt exemple
$
$ echo .[!.]*
.profile
. sh_history
Remarque:
Après un unset PATH, les ls sont "not found", alors que la commande pwd fonctionne, car elle est intégrée au shell. Il faudra alors par exemple ouvrir un autre terminal (voir le fichier /etc/profile qui définit PATH).
2.8.1) Expressions génériques composées du Korn-shell
En complément aux expressions génériques simples (ci-dessus) largement utilisées, les notations suivantes existent en Korn-shell :
Caractère | Description |
---|---|
*(expr1|expr2|...) | Un nombre quelconque d'apparitions d'une des expressions (éventuellement aucune) |
+(expr1|expr2|...) | Un nombre quelconque d'apparitions d'une des expressions (au moins une) |
?(expr1|expr2|...) | Au plus une apparition d'une des expressions |
@(expr1|expr2|...) | Exactement une des expressions |
!(expr1|expr2|...) | Aucune des expressions |
Exemples:
Caractère | Description |
---|---|
*([A-Z]|[0-9]) | Le résultat de la commande est inséré dans la liste d'arguments |
+([A-Z]|[0-9]) | Chaîne dont chaque élément est soit une majuscule soit un chiffre (chaîne vide exclue) |
?([A-Z]|[0-9]) | Chaîne vide ou d'un élément qui est soit une majuscule soit un chiffre |
@([A-Z]|[0-9]) | Chaîne d'un élément qui est soit une majuscule soit un chiffre |
!([A-Z]|[0-9]) | Chaîne ne comportant ni majuscule ni chiffre |
Remarques:
' ': simples côtes, à lintérieur rien nest interprété
" ": doubles côtes, à lintérieur rien nest interprété sauf $, " et `
` `: interprété et remplacé par son résultat
Le double caractère est intéressant dans lexemple: echo "lhistoire $PATH"
2.8.2) Substitutions de commandes
Caractère | Description |
---|---|
`commande` | Le résultat de la commande est inséré dans la liste d'arguments |
$(commande) | Syntaxe recommandée |
prabou@prabou-VPCZ23C5E:~$ rep=`pwd` prabou@prabou-VPCZ23C5E:~$ echo "Repertoire courant : $rep" Repertoire courant : /home/prabou prabou@prabou-VPCZ23C5E:~$ echo "Il est $(date +%H:%M:%S)" Il est 16:46:58 prabou@prabou-VPCZ23C5E:~$
2.8.3) Caractères de protections
Caractère | Description |
---|---|
\ | Le caractère qui suit perd son rôle fonctionnel |
' ' | Tous les caractères situés entre les simples quotes perdent leur rôle fonctionnel |
" " | Tous les caractères situés entre les doubles quotes perdent leur rôle fonctionnel sauf $ (valeur de variable) et `` (résultat de commande). Mais il y a possibilité de banaliser $ et ' |
Afficher ou non le caractère *:
$ echo *
fic1 fic2 essai99 fic.txt
$ echo \*
*
fic1 fic2 essai99 fic.txt
$ echo \*
*
Annuler ou non la substitution de commandes:
$ echo "La date est `date`"
La date est Mon Jan 03 15 :58 :39 GMT 2000
$ echo 'La date est `date`'
La date est `date`
La date est Mon Jan 03 15 :58 :39 GMT 2000
$ echo 'La date est `date`'
La date est `date`
2.8.4) Procédures et paramètres
Des séquences de commandes et d'instructions shell peuvent être regroupées dans un fichier qui devient ainsi une nouvelle commande ou "procédure" ou "script".
2.9) Structure et exécution d'un script shell
Un script shell peut contenir de manière générale:
Une ligne de désignation de l'interpréteur
des commandes UNIX, des commandes internes shell
des structures de contrôle (instructions conditionnelles, boucles, aiguillages, etc ...)
des commentaires
L'exécution est demandée de manière implicite en appelant le nom du script:
$ vi prog.ksh
#!/bin/ksh
#-- commentaires --
#-- code - exit 0
$ chmod +x prog.ksh #on attribue les droits d'execution pour le script prog.ksh
$ ./prog.ksh
#!/bin/ksh
#-- commentaires --
#-- code - exit 0
$ chmod +x prog.ksh #on attribue les droits d'execution pour le script prog.ksh
$ ./prog.ksh
2.10) Commentaire et shell interpréteur d'un script
Le caractère # introduit un commentaire jusqu'à la fin de la ligne en cours (il nexiste pas de caractère(s) de début et fin de commentaire).Par défaut, le script est interprété par un shell fils du shell de connexion et ne reçoit que les variables de l'environnement validées grâce à l'instruction export. La première ligne du script (parfois appelée shebang ou directive d'exécution) est importante car elle permet d'indiquer l'interpréteur choisi pour l'exécuter. Si cette ligne est omise, le shell interpréteur choisi sera par défaut le même que le shell interactif d'où est lancé l'exécution. Il est recommandé de toujours faire apparaître explicitement cette désignation de l'interpréteur.
Remarque: un avantage de nommer un programme *.sh cest quon évite une commande UNIX par défaut.
2.11) Code retour et traitement associé
Les scripts peuvent retourner un code retour via l'instruction de sortie exit n . La tradition est de retourner 0 en cas de succès et une valeur dans l'intervalle [1 , 255] sinon.Exemple: sortir du script en retournant la valeur 3
$ cat prog.ksh
#!/usr/bin/ksh
exit 3
$ ./prog.ksh
$ echo $?
3
#!/usr/bin/ksh
exit 3
$ ./prog.ksh
$ echo $?
3
2.12) Interprétation d'une ligne de commande
Le shell interprète chaque ligne d'un script suivant un ordre donné: Substitutions de variables,
Substitutions de commandes,
Traitement des redirections et tubes,
Traitement des caractères spéciaux sur les noms de fichiers,
Appel de la commande (via "fork") ou de l'instruction.
2.13) Paramètres du script
Il est possible de fournir de l'information au script lors de son exécution en utilisant des paramètres (ou arguments) sur la ligne de commande. Les valeurs saisies (chaînes de caractères) sont automatiquement mises dans les variables système 1, 2, 3, 4, ...Les variables complémentaires # et * contiennent alors respectivement le nombre de paramètres saisis et la liste concaténée de tous les paramètres.
Exemple 1 - procédure élémentaire gérant les paramètres de la ligne de commandes:
prabou@prabou-VPCZ23C5E:~$ cat prog.sh #!/bin/bash echo "Premier argument : $1" echo "Nombre d'arguments: $#" echo "Liste des arguments : $*" exit 0 # Résultat de l'exécution prabou@prabou-VPCZ23C5E:~$ ./prog.sh un deux quatre Premier argument : un Nombre d'arguments: 3 Liste des arguments : un deux quatre prabou@prabou-VPCZ23C5E:~$
Exemple 2 - procédure élémentaire affichant la taille en octets du fichier passé en premier argument, et retournant le code 3 d'erreur sinon:
$ cat preg.ksh
#!/usr/bin/ksh
echo "Taille du fichier: $(wc -c $1)"
exit 0
#!/usr/bin/ksh
echo "Taille du fichier: $(wc -c $1)"
exit 0
Résultat de l'exécution lorsque le fichier exemple existe:
$ prog.ksh exemple
Taille du fichier : 1242 exemple
$ echo $?
0
Taille du fichier : 1242 exemple
$ echo $?
0
Chapitre 3: Programmation shell
Objectifs: Instructions conditionnelles - if/then/else
Traitement des flux - for, while, until
Lecture au clavier
Expressions arithmétiques
Branchements - case
Fonctions
3.1) Instructions conditionnelles et tests
Instructions conditionnelles: if/then/else
Structure essentielle de contrôle
3.1.1) L'instruction if
Syntaxe:
if commande then liste_de_commandes fi ou if commande ; then liste_de_commandes fi ou if commande then liste_de_commandes else liste_de_commandes fi
Note: Il est possible de placer plusieurs commandes après le "if". Dans ce cas, le test prend en compte le code retour de la dernière de ces commandes.
Exemples simples de syntaxe:
3.1.2) Instructions conditionnelles composées : if imbriquésif who | grep stage1 > /dev/null ; then echo "stage1 est connecte" fia=1 if [ $a eq 1 ] then echo "a=$a" fiif date ; who | grep root > /dev/null then echo "root est connecte" else echo "root n'est pas connecte" fi
Syntaxe:
if commande then liste_de_commandes else if commande then liste_de_commandes else if commande then liste_de_commandes else #Ce "else" est bien sur facultatif liste_de_commandes fi fi fi
Attention! L'utilisation de la syntaxe en deux mots else if nécessite autant de fi que de if.
Autre forme (lif) (ne nécessite qu'un seul "fi" fermant):
if commande then liste_de_commandes elif commande then liste_de_commandes elif commande then liste_de_commandes else #Ce "else" est bien sur facultatif liste de commandes fi
3.1.3) Instructions conditionnelles compactes: opérateurs && et ||
Ces notations exploitent le code retour. Elles permettent de faire des instructions conditionnelles sur une ligne.
cde1 && cde2 Lancer la deuxième commande si la première a réussi (exit 0).
cde1 || cde2 Lancer la deuxième commande si la première a échoué ( exit avec code retour différent de 0 ).
$? Code retour de la dernière commande appelée.
Exemples:
$ ( who | grep stage1 ) || echo "stage1 non connecte" stage1 non connecte $ ls exemple > /dev/null 2>&1 && lp exemple #lp redirection vers l'imprimante
3.1.4) La commande test
La commande test, les [ ] et les [[ ]]:
Utilisation de la commande test
Utilisation des [ ]
Utilisation des [[ ]] (Korn Shell)
Cette commande évalue une expression booléenne et retourne la valeur 0 si cette expression est vraie.
Il s'agit donc d'une commande assez indispensable pour réaliser certains tests via les instructions du shell.
test expression ou [ expression ]
Note: Les crochets doivent être délimités par des espaces.
Quelques expressions possibles:
Expression | Description |
---|---|
"chaîne1"="chaîne2" | Les deux chaînes sont identiques |
"chaîne1"!="chaîne2" | Les deux chaînes sont différentes |
-z "chaîne" | La chaîne est de longueur nulle |
-n "chaine" | La chaîne est de longueur non nulle |
entier1 -eq entier2 | Les deux entiers sont égaux |
Autres opérateurs "entiers" -ne -gt -ge -lt -le | |
-e fichier | Le "fichier" existe (on peut aussi utiliser - a, mais considéré comme obsolète). |
-r fichier | Droit de lecture sur "fichier" |
-w fichier | Droit d'écriture sur "fichier" |
-x fichier | Droit d'exécution sur "fichier" |
-u fichier | Le bit SUID est positionné |
-g fichier | Le bit SGID est positionné |
-k fichier | Le "sticky bit" est positionné |
-f fichier | Il s'agit d'un fichier ordinaire |
-d fichier | Il s'agit d'un répertoire |
-c fichier | Il s'agit d'un fichier spécial de type caractère |
-b fichier | Il s'agit d'un fichier spécial de type bloc |
-L fichier | Il s'agit d'un lien symbolique |
-s fichier | Le fichier est de taille non nulle |
! | Négation |
-o | OU |
-a | ET (plus prioritaire que le OU) |
Exemples simples de syntaxe:
if test $# -eq 0 ; then echo "Usage: $0 argument"; exit 1 fi
if test $# -eq 0 ### ou [ $# -eq 0 ] then echo "Usage: $0 argument" exit 1 fi
if test -f $1 then echo "$1 est un fichier ordinaire" elif [ -d $1 ] then echo "$1 est un repertoire" elif [ -L $1 ] then echo "$1 est un lien symbolique" else echo "Ni fichier ordinaire, ni repertoire, ni lien symbolique" fi if test -f $1 -a -x $1 then echo "$1 est un fichier ordinaire et executable" fi
midi=12 heure=`date '+%H'` if test $heure -ge $midi then echo "Il est plus de midi" else echo "Il n'est pas encore midi" fi
if [ ! -d $1 -a ! -L $1 ] ; then echo "$1 ressemble a un fichier ordinaire" fi
Remarques:
- man test affichera toutes les options
- il faut un espace après le [ et avant le ]
3.1.5) Enrichissement de la commande test du Korn-Shell
Le ksh introduit quelques nouvelles expressions intéressantes:
Expression | Description |
---|---|
-O fichier | Est-on propriétaire du fichier? |
-G fichier | On fait partie du groupe propriétaire du fichier? |
fic1 -nt fic2 | Le premier fichier est-il plus récent que le deuxième fichier? |
fic1 -ot fic2 | Le premier fichier est-il plus ancien que le deuxième fichier? |
fic1 -ef fic2 | S'agit-il de deux liens sur le même fichier physique? |
Exemple:
if [ $1 -ot $2 -a $3 -ef $2 ] then echo "$1 est plus ancien que $2" echo "$2 et $3 sont deux liens sur le meme fichier" fi
Une nouvelle syntaxe est possible en ksh
[[ expression ]]
L'intérêt essentiel de cette nouvelle syntaxe est la possibilité d'utiliser des expressions génériques (simples ou composées). L'analyse sémantique de chaînes de caractères sera désormais possible dans l'instruction de test.
Par ailleurs les opérateurs logiques ET et OU sont remplacés par:
|| | OU (remplace l'opérateur -o) |
&& | ET plus prioritaire que le OU (remplace l'opérateur -a) |
Exemple de syntaxe:
#!/usr/bin/ksh if [[$option = @(+|-)+([a-z]) && $var = ?(+|-)+([0-9]) ]] then ... fi
3.2) Traitement sur flux: les boucles
3.2.1) La boucle for
Cette boucle permet d'exécuter plusieurs fois une liste de commandes. A chaque pas de boucle, la variable choisie comme indice prend une valeur dans une liste donnée.
for variable in liste_de_valeurs do liste_de_commandes done
1) Boucler sur tous les paramètres de la procédure
for i in $* do liste_de_commandes done
2) Boucler sur tous les noms de fichiers du répertoire courant
for i in * do liste_de_commandes done
3) Faire cinq fois un traitement
for i in 1 2 3 4 5 do liste_de_commandes done
3.2.2) Les boucles while et until
La boucle while permet d'exécuter une liste de commandes tant qu'une condition est réalisée. La boucle until permet d'exécuter une liste de commandes jusqu'à ce qu'une condition soit réalisée.
while condition_r\'ealis\'ee do liste_de_commandes done ou until condition_r\'ealis\'ee do liste_de_commandes done
Exemple de syntaxe:
who | grep $1 > /dev/null while [ $? -eq 0 ] do echo "$1 est connecte" sleep 15 who | grep $1 > /dev/null done echo "$1 n'est pas ou n'est plus connecte" exit 0
3.2.3) Instructions de branchement
Il est possible d'utiliser des instructions de branchement pour sortir brutalement des boucles ou pour sauter les instructions restantes du corps de boucle:
break [ n ]: Quitter brutalement une boucle. L'éventuel paramètre n permet de quitter n niveaux de boucles imbriquées.
continue [ n ]: Retourner au test ( while et until ) , passer à la valeur suivante ( for).( éventuellement pour n niveaux)
Exemples:
Ne pas faire la deuxième partie du traitement pour la 5ème itération de la boucle:
while [$i -lt 100 ] do ... if [ $i = 5 ] ; then continue fi ... done
Quitter la 2ème boucle imbriquée au premier répertoire trouvé:
while true do ... for f in *.txt do if [[ -d $f ]] then break 2 fi ... done done
3.3) Lectures au clavier : read
Syntaxe: read liste_de_variablesCette commande lit une ligne au clavier. Par exemple:
#!/usr/bin/ksh echo "Entrez la valeur : \c" read var echo "Vous avez saisi la valeur $var" exit 0
Dans le cas où la commande read a plusieurs variables en arguments, la ligne lue au clavier est "découpée" en champs. Le séparateur par défaut en lecture est : espace ou tabulation.
#!/usr/bin/ksh echo "Entrez les valeurs: \c" read i j k echo "valeur de i: $i" echo "valeur de j: $j" echo "valeur de k: $k"
Exécution:
$ prog.ksh Entrez les valeurs: 12 4 143 (saisie clavier) valeur de i: 12 valeur de j: 4 valeur de k: 143
Note : Dans la commande" test notamment, il est important de gérer la possible "lecture vide" en utilisant judicieusement les doubles quotes ou via un test préalable. Il convient en effet de toujours fournir le nombre d'arguments attendus à cette commande.
3.3.1) Nouvelles possibilités en Korn-shell
On peut poser une question et lire la réponse en une seule instruction. Par exemple:
read reponse? "Voici la question? "
équivaut à
echo "Voici la question? \c"; read reponse
3.4) Expressions arithmétiques
3.4.1) La commande expr (Bourne shell)La commande expr permet d'interpréter des variables shell comme des entiers dans le cadre d'une expression numérique. Le résultat de cette évaluation peut être stockée dans une variable résultat via l'opérateur de substitution de commande.
Les opérateurs disponibles sont: + - * / ( division entière) % ( modulo )
while [ $n -lt 100 ] do ..traitement... n='expr $n + 1' done a=5 ; b=11 mult='expr $a \* $b' div='expr $a / $b'
3.4.2) Expressions arithmétiques Korn shell
Le Korn-Shell possède une commande interne qui permet d'évaluer des expressions arithmétiques. Les opérateurs utilisables sont proches de ceux du langage C.
Syntaxe: let expression ou (( expression ))
Exemples de syntaxe:
_________________________________________________
x=10
let x=x+1: On ne doit pas utiliser d'espaces avec la commande let
_________________________________________________
x=3
(( x=x*2 )) Les doubles parenthèses permettent de mettre des espaces
_________________________________________________
x=3
(( x=(x-2)*3 )) Les parenthèses modifient les priorités des opérateurs
_________________________________________________
3.4.3) Possibilités complémentaires
let et (( )) peuvent être utilisées directement dans un test, afin d'effectuer des comparaisons numériques. Il faut alors utiliser les notations <, <=, >, >= (issues du langage C).
while (( i < 100 )) do ... done
integer peut être utilisée pour déclarer des variables comme des entiers; cela permet de bâtir une expression "entière" directement:
integer i=0 i=i+1
3.5) Branchements
3.5.1) Instruction case
Syntaxe:
case valeur in motif1) liste_de_commandes ;; motif2) liste_de_commandes ;; ....... esac
Les différents motifs sont examinés dans l'ordre. Si un des motifs correspond à la valeur de test, la liste de commandes correspondante est exécutée et il y a ensuite sortie de l'instruction.
Les motifs peuvent contenir des expressions génériques simples ou composées.
On peut citer notamment:
Le caractère | (pipe) peut être utilisé pour réaliser un OU.
Le motif * peut être utilisé comme dernier motif et jouer ainsi le rôle de "cas par défaut".
Exemple simple de syntaxe:
#!/usr/bin/sh case $# in 1|2) echo "On a recu 1 ou 2 arguments" echo "on enchaine apres l'aiguillage" ;; 3) echo "On a recu 3 arguments" echo "on enchaine apres l'aiguillage" ;; *) echo "Mauvais appel, il faut 1 ou 2 ou 3 arguments" exit 1 ;; esac echo "Suite du traitement" exit 0
3.5.2) Instruction select du Korn-Shell
Cette instruction est proposée pour programmer des menus.
Elle se comporte comme une boucle et enchaîne les opérations suivantes:
Affichage d'une suite de libellés numérotés automatiquement,
Affichage de la variable système PS3,
Lecture clavier du choix de l'utilisateur,
La valeur d'index est positionnée avec le libellé correspondant au choix et la variable système REPLY contient le numéro correspondant. En cas de choix impossible, la valeur d'index contient la chaîne vide. En cas de réponse vide, le menu est réaffiché.
Syntaxe:
select variable in liste de libelles do Aiguillage sur $variable ou $REPLY done
Exemple de syntaxe:
PS3="Tapez votre choix: " select i in "Liste" "Ajout" "Modification "Sortie" do case $REPLY in 1|2|3) echo $i 4) echo $i exit 0 ;; *) echo "Choix impossible" ;; esac done
Résultat d'une exécution:
$ menu.ksh 1) Liste 2) Ajout 3) Modification 4) Sortie Entrez votre choix: 1 Liste Entrez votre choix: 3 Modification Entrez votre choix: (Saisie vide) 1) Liste 2) Ajout 3) Modification 4) Sortie Entrez votre choix: 5 Choix impossible Entrez votre choix: 4 Sortie $
3.6) Fonctionnalités complémentaires
3.6.1) Les tableaux en Korn-Shell
(Remarque: pas de tableau en bourne shell)
Le Korn-shell permet la manipulation de tableaux unidimensionnels. Un tableau est vu par le shell comme un empilement de variables classiques (chaînes de caractères ASCII) manipulées avec une convention de nommage. Il n'y a aucune réservation préalable en mémoire. L'indice 0 désigne le premier élément du tableau.
Affectation globale par initialisation d'un tableau (si le tableau existe déjà, il est réinitialisé)
$ set -A tab valeur1 valeur2 valeur3
Désignation des éléments
$ echo ${tab[2]}: Le troisième élément
valeur3 (les indices commencent à zéro)
$ echo $tab: Le premier élément. $tab ou ${tab[0]} sont valeur1 deux autres notations pour le premier élément
$ echo ${tab[*]}: Tous les éléments
valeur1 valeur2 valeur3
Affectation d'un élément
$tab[0]=premier $echo ${tab[*]} premier valeur2 valeur3
echo $#tab[*] 3
Conformément à sa structure d'empilement de variables, on peut affecter n'importe quel élément (éventuellement hors de la plage de départ). Dans ce dernier cas, tous les éléments d'indice intermédiaire n'existent pas, ils ne sont donc pas comptés dans le nombre d'éléments du tableau.
$ tab[100]=dernier $ echo ${tab[*l} premier valeur2 valeur3 dernier $ echo ${#tab[*]} 4
3.6.2) Redirections particulières de l'entrée standard: Script en ligne
_________________________________________________
<
<<\mot "mot" marquera la fin de l'entrée standard, les caractères spéciaux éventuels ne seront pas interprétés.
_________________________________________________
Exemples:
1) Afficher au terminal du texte et réaliser les expansions de variable et commandes si besoin:
#! /usr/bin/sh cat « fin Ceci est l'entree standard de la commande Type du terminal = $TERM Il est $ (date +%H,%M ) fin exit a
Résultat d'une exécution
Ceci est l'Entree standard de la commande Type du terminal = vt100 Il est 10,05
2) Afficher au terminal du texte et NE PAS réaliser les expansions de variables, ni de commandes:
#!/usr/bin/sh cat << \fin Ceci est l'Entree standard de la commande Type du terminal = $TERM Il est $(date +%H:%M) fin exit 0
Résultat d'une exécution:
Ceci est l'Entree standard de la commande Type du terminal = $TERM Il est $(date +%H:%M)
3) Envoyer un mail depuis un script:
$ cat prog.ksh #!/usr/bin/ksh mail $1 -s test « FIN Ce mail vous est envoye automatiquement par $0 a $(date) Excellente journee a vous ! FIN exit 0
Exemple d'une exécution:
$ ./prog.ksh contact@societe.com $
3.6.3) Gestion des Entrées/Sorties Compléments
Les entrées/sorties:
0 entrée standard
1 sortie standard
2 sortie des erreurs standard
A l'intérieur d'un script, la commande exec permet d'ouvrir des fichiers en leur associant des descripteurs.
Les numéros 0, 1et 2 sont déjà attribués aux entrée/sortie standards (entrée, sortie, erreur).
On peut, par exemple, utiliser les notations suivantes:
_________________________________________________
exec n>fichier Ouverture d'un fichier en lecture (descripteur n)
_________________________________________________
exec n>fichier Ouverture d'un fichier en écriture (descripteur n)
_________________________________________________
Par la suite, dans votre programme, une utilisation des redirections Unix en mentionnant le numéro de descripteur permet de lire ( <&n ), notamment avec read, ou d'écrire ( >&n) , notamment avec echo ou printf dans les fichiers correspondants.
C'est en particulier un moyen propre de lire un fichier texte ligne à ligne dans un script.
On dispose également des notations <&- et >&- pour fermer les descripteurs:
_________________________________________________
exec <&- Fermeture du descripteur de fichier n
_________________________________________________
exec >&- Fermeture du descripteur de fichier n
_________________________________________________
Exemple de syntaxe:
#!/usr/bin/sh ### # Ouverture du 1er fichier en lecture exec 3< fic1 # Ouverture du 2eme fichier en Ecriture exec 4> fic2 #Lecture ligne par ligne depuis le 1er fichier while read <&3 ligne do # Ecriture sur la sortie standard echo $ligne echo "Copier(o/n - lecture vide pour sortir)? \c" # Lecture depuis l'entrée standard read rep if test -z "$rep" then break fi if test "$rep" = o then # Ecriture dans le 2eme fichier echo $ligne >&4 fi done exit 0
Exemple de syntaxe dans le cas particulier des commandes internes reaci/print du Korn-Shell:
Les commandes read et print sont intégrées au Korn-Shell et possèdent une option -u permettant de préciser le descripteur à traiter.
#!/usr/bin/ksh # Ouverture du 1er fichier en lecture exec 3< fic1 # Ouverture du 2eme fichier en ecriture exec 4> fic2 # Lecture ligne par ligne depuis le 1er fichier while read -u3 ligne do #Ecriture sur la sortie standard print $ligne print "Copier(o/n - lecture vide pour sortir)? \c" #Lecture depuis l'entrée standard read rep if test -z "$rep" then break fi if test "$rep" = o then # Ecriture dans le 2eme fichier print -u4 $ligne fi done
3.6.4) La variable IFS
La variable système IFS indique quel est le séparateur de champs lors des lectures (read) et des résultats de substitutions de commande ou de paramètres.
Sa valeur par défaut est "un blanc": Espace, Tabulation et Saut de ligne.
Exemple:
IFS=: for i in $PATH do echo $i done
Note: Le shell utilise aussi cette variable lors de l'évaluation de la ligne de commande: le caractère défini par IFS est remplacé par un blanc avant le lancement de la commande. En particulier, la commande echo $IFS n'est pas un bon moyen de connaître la valeur de IFS!
3.6.5) L'opérateur shift
Cet opérateur permet de parcourir la liste des paramètres en renommant ceux-ci à partir du deuxième. ($1 disparaît, $2 devient $1, $3 devient $2 etc ...)
Bien entendu, le nombre de paramètres $# est décrémenté et la liste $* est mise à jour.
En Bourne-shell, on ne peut désigner que 9 paramètres à la fois, la notation $10 n'existe pas.
En Korn-shell, cette limitation est levée via des notations telles que ${10}.
Concrètement, l'opérateur shift peut servir dans les commandes à options pour se positionner, après traitement syntaxique de ces dites options, au début de la liste des véritables arguments.
Note: Il est possible de décaler plusieurs arguments à la fois: shift n
Exemple:
#!/usr/bin/sh #Exemples d'utilisation de shift pour afficher le premier #argument et le dernier echo "premier: $1" shift $#-1 echo "dernier $1"
3.6.6) L'opérateur set
Cet opérateur présente de multiples facettes à usages plus ou moins fréquents.
Les possibilités les plus utiles sont les suivantes:
Sans arguments, il donne la liste de toutes les variables définies.
Avec des arguments, l'opérateur permet de repositionner un nouvel ensemble de paramètres ($1, $2 ...).
Exemple:
$ set un deux trois $ echo $* un deux trois
$ who -r .run-level 2 Jun 21 14:10 2 0 S $ set 'who -r' $ echo $5 $4 $6 21 Jun 14:10
Note: Avec deux signes moins (--), l'opérateur set permet, en une seule commande, de libérer tous les paramètres de position
$set -- $ echo $* kSh: *: parameter not set $
Avec des options, il permet différents paramétrages du shell. Les options peuvent être abrégées (voir détail ci-dessous).
Option | Description |
---|---|
set -o option | Active l'option |
set +o option | Désactive l'option |
set -o | Affiche les options et leur état respectif |
Quelques options possibles:
allexport ( -a ) | Exportation systématique de toute variable du shell |
errexit ( -e ) | Sortie du shell sur toute erreur |
ignoreeof | Sortie du shell par exit (pas de "Ctrl-d") |
monitor | Avertissement lors de fin de tâche |
noclobber | Pas d'écrasement via les redirections (on doit forcer par >|) |
noexec ( -n ) | Analyse mais n'exécute pas (pour chercher des erreurs de syntaxe) |
noglob ( -f ) | Pas de traitement des caractères spéciaux |
nounset ( -u ) | Génération d'une erreur sur tentative d'acces à une variable non existante |
verbose ( -v ) | Mode trace (pour chercher les erreurs) |
vi | Mode de rappel et edition de commandes avec vi |
xtrace ( -x ) | Autre mode trace sans expansion des variables |
etc... |
$ set -o Current option settings ... noclobber off ... $ set -o noclobber $ set -o Current option settings ... noclobber on ... $ ls la / > liste $ ls ial /usr > liste ksh: /tmp/liste: file already exists $ ls ial /usr >1 liste $ set +o noclobber $ set -o Current option settings ... noclobber off ... $
3.6.7) Gestion des signaux
Exécuter une action lorsque se produit un certain événement.
Syntaxe:
trap 'action' evenement
L'action exécutée peut être soit:
Une liste de commandes
Une commande vide " (pour ignorer un événement)
Note: Le signe - (moins ou action non mentionnée) rétablit le comportement par défaut.
L'évènement déclenché peut être soit:
Un nom de signal
Un numéro de signal
Par exemple:
Signal | Nom | Description |
---|---|---|
2 | INTR | Interruption clavier |
3 | QUIT | Interruption clavier (Ctrl \) générant un fichier "core" |
15 | TERM | Commande : "kill PID" (sauf kill -9 qui ne peut pas être intercepté) |
0 | EXIT | Déconnexion (fin du shell) |
numéro | ERR | Erreur retournée par une commande |
Exemples:
fictemp=/tmp/fic$$ trap 'rm -f $fictemp; exit 1' INTR trap '' 2 3 trap - 2 3 trap '$HOME/.logout' EXIT
3.6.8) Autres commandes internes
eval : évaluation whence : chemin d'accés Autres commandes internes : - deux-points: commande vide typeset: typer les variables
print: affichage
printf: affichage formaté
eval: évaluation (permet d'évaluer une commande avant son exécution, par exemple si une variable contient une commande)
whence: chemin d'accès (sur toutes les plateformes)
: (deux points) Commande vide retournant toujours 0 ( permet notamment de constituer des boucles infinies)
typeset Affecter des attributs à des variables
Option Description -u Transformation des minuscules en MAJUSCULES
-l Transformation des MAJUSCULES en minuscules
-r Lecture seulement (variable non modifiable)
-i Type entier (integer est un alias sur typeset -i)
etc ... 1$ t ype se t -0 $ echo $var ABCD $ var=abcd print et printf: La commande "print" veut mettre fin aux diverses variantes de la commande echo. Elle accepte les caractères conventionnels suivants:
\a Signal sonore \n Saut de ligne \b Retour arrière \c Pas de saut de ligne \r Retour chariot \t Tabulation \f Effacement d'écran ou saut de page \v Tabulation verticale La commande print intégrée au Korn-Shell possède une option -u permettant de préciser le descripteur à traiter. L'option -u2 permet d'écrire sur l'erreur standard:
$ 'print -u2 "Ceci est un message d'erreur" Ceci est un message d'erreur $ La commande "printf" est très similaire à la fonction de même nom du langage C et permet de réaliser des sorties formatées. Par exemple : $ printf "Nom %-155, Prenom %-155\n" "Jean" "Dupont" Nom : Jean Prenom Dupont $ Formats courants : Forrnat Exemple Description %d %3d 3 chiffres (digit), cadré à droite. %s %-10s Chaine de caractère (string), cadré à gauche. %f %2.3f Nombre réel, arrondi à trois chiffres après la virgule, cadré à gauche.
%d %3d 3 chiffres (digit), cadré à gauche. Note: Penser à placer un \n (saut de ligne) à la fin de la chaîne de caractère à afficher.
eval - Le shell étend les arguments de "eval" en les séparant par un espace puis traite la chaîne résultat comme une commande.
Cette double évaluation est utile lorsque les arguments de "eval" contiennent des symboles de redirection ou des substitutions de variables.
Quelques exemples:
$ var=toto toto=lOO $ print \$$var $toto $ eval print \$$var 100 $ cat essai #!/usr/bin/sh print IlLe dernier argument est \$$#11 eval print ltLe dernier argument est \$$#11 exit 0 Lancement du script essai:
$ essai a b e d Le dernier argument est $4 Le dernier argument est d $ Créer une variable uid avec la valeur de l'UID du login en cours:
$ id uid=sOl(stagel) gid=sOO(stage) $ eval 'id 1 eut d' (' fl' $ eeho $uid 501 whence [ -V ] commande La commande whence trouve le chemin d'accès à la commande. Avec l'option -v, la commande whence signale s'il s'agit d'un alias ou d'une commande interne.
Exemples $ whence ps /usr/bin/ps $ whence -v ps ps is /usr/bin/ps $ $ whenee eeho eeho $ whenee -v eeho echo is a shell builtin $ $ whenee l /usr/bin/ls -al $ whenee -v l l is an alias for /usr/bin/ls -al $ wai t [ n 1 %n ] Attendre la fin d'un processus lancé en arrière-plan Le nombre n indique le PID du processus concerné, %n le numéro de job Sans arguments, la commande wai t attend la fin de tous les pro cess us- fils. Exemple Attendre la fin du processus de PID 11902 [1] 11902 ~ wa1t 11902 Attendre la fin du premier processus lancé en arrière plan: job %1 $ sleep 20 & [1] 11904 $ sleep 30 & [2] 11905 $ wait %1
3.7) Fonctions
3.7.1) Principe et propriétés
Une fonction est un sous-programme qui peut être appelé de la même manière qu'un commande depuis le programme principal.
Syntaxe:
function nom { ........ }
NB : l' "ancienne syntaxe" compatible Bourne-shell est aussi possible:
nom () { ........ }
Pour pouvoir être appelée par un script, une fonction doit être disponible dans le shell interpréteur du script. Pour cela, le moyen le plus simple consiste à écrire la fonction dans le même fichier que le programme appelant. Nous verrons par la suite des solutions permettant de partager des fonctions entre programmes.
Les fonctions peuvent:
Recevoir des arguments (qui seront traités comme des paramètres de position),
Modifier un argument reçu,
Retourner une valeur via l'instruction "return n" (qui positionnera $? à la valeur de n),
Utiliser des variables locales définies via l'instruction "typeset".
3.7.2) Transmission d'arguments
Le programme appelant la fonction peut lui fournir des arguments. Ils seront récupérés par les variables $1, $2, $3 qui deviennent donc locales à la fonction rendant les arguments passés au programme inaccessibles.
Exemple:
#!/usr/bin/ksh function f { echo $1 $2 } echo bonjour f marseille paris exit 0
$prog.ksh bonjour marseille paris
Remarque:
Il faut dans un script sourcer le fichier qui contient les fonctions:
#!/bin/sh ... ... . fonction.lib #fichier contenant les fonctions, ce fichier n'a pas besoin des droits d'exécution.
3.7.3) Modification d'un argument reçu
Il est possible d'utiliser une chaîne de caractères transmise en argument pour créer ou modifier une variable. Ce mécanisme repose sur le fait que les variables shell sont globales par défaut (visibles et modifiables par tous les sous- programmes)
Exemple:
#!/usr/bin/ksh function f { echo "debut de l'execution de la fonction" echo "saisir la valeur de $1 : \c" read $1 echo "fin de l'execution de la fonction" } echo bonjour f var echo "valeur de var dans le programme principal:$var"
$./prog.ksh bonjour debut de l'execution de la fonction saisir la valeur de var : 1250 fin de l'execution de la fonction valeur de var dans le programme principal : 1250 $
3.7.4) Envoi d'un code retour avec return
L'instruction return pour la fonction joue exactement le rôle de exit pour le programme principal, c'est à dire:
elle interrompt l'exécution de la fonction et revient au programme principal;
elle donne aussi la possibilité d'envoyer une valeur qui sera le code retour de l'exécution de la fonction (cette valeur sera donc mise dans la variable $?)
Exemple:
#!/usr/bin/ksh function f { if [ $# = 0 ] ; then echo "pas d'arguments pour f" ; return 1 fi ... } echo bonjour f echo "code retour de f : $?" ; echo fin
$ proc.ksh bonjour pas d'arguments pour f code retour de f : 1 fin $
3.7.5) Utilisation de variables locales
Par défaut, les variables shell sont globales. Afin de disposer de variables de travail dont la portée est restreinte à la fonction, il est possible de définir des variables locales avec l'instruction typeset.
Note: L'éventuelle valeur initiale de la variable est sauvegardée et restaurée au retour dans le programme principal.
Exemple:
#!/usr/bin/ksh function f { typeset var=marseille echo "valeur de var dans f $var" } echo bonjour var=paris f echo "valeur de var dans proc : $var" echo fin exit 0
$proc.ksh bonjour valeur de var dans f : marseille valeur de var dans proe : paris fin $
3.7.6) Partage de fonctions
Il est possible de partager des fonctions entre différents programmes shell, suivant 2 modes : statique ou dynamique
Partage statique
Le principe est de rendre la fonction disponible dans le shell interpréteur du nouveau programme, en forcant son chargement. Cette opération est réalisée à l'aide de l'opérateur . (point).
L'inconvénient principal de cette méthode est le possible chargement dans le shell interpréteur de fonctions inutiles.
Exemple:
$ cat /var/fonctions/lib.ksh #!/usr/bin/ksh function f { echo "Bienvenue dans f !" }
Utilisation :
$ cat prog.ksh #!/usr/bin/ksh . /var/fonctions/lib.ksh echo "appel de f : " f echo fin
Exécution:
$ prog.ksh Appel de f: Bienvenue dans f ! fin
Partage dynamique en Korn-shell
Plus performante, cette méthode consiste à provoquer le chargement de la fonction uniquement lors de son premier appel. Par la suite, la fonction reste chargée en mémoire.
Mise en oeuvre:
1. Définition d'un fichier $ENV dans le fichier .profile (en général, .kshrc);
2. Création d'un fichier de même nom que la fonction contenant le code de la fonction;
3. dans $ENV, définir la variable FPATH donnant le chemin du fichier de la fonction à partager ET appeler l'instruction autoload sur la fonction;
4. dans tous les scripts appelant la fonction, forcer l'exécution dans le shell courant du $ENV.
La commande typeset - fu permet de lister les fonction" autochargées" dans le shell courant.
Exemple:
$ cat $HOME/$ENV ... FPATH=/var/fonctions_autoload autoload f ... $ cat /var/fonctions_autoload/f function f { echo "Bienvenue dans f !" } $
$ cat prog.ksh #!/usr/bin/ksh . $ENV echo "appel de f:" f echo fin
$ prog.ksh appel de f: Bienvenue dans f! fin $
Chapitre 4: Utilitaire et commandes Unix
Objectifs: Utilisation des utilitaires standards
Rappel de certaines licences liées aux utilitaires disponibles optionnellement
4.1) Les différentes licences
Les différentes licences
GNU GPL
LGPL
Logiciels gratuits graticiels
4.1.1) La licence publique générale GNU
La licence publique générale GNU (ou GNU General Public License son seul nom officiel en anglais, communément abrégé GNU GPL voire simplement couramment "GPL") est une licence qui fixe les conditions légales de distribution des logiciels libres du projet GNU. Richard Stallman et Eben Moglen, deux des grands acteurs de la Free Software Foundation, en furent les premiers rédacteurs.
Elle a depuis été adoptée, en tant que document définissant le mode d'utilisation, donc d'usage et de diffusion, par de nombreux auteurs de logiciels libres. La principale caractéristique de la GPL est le copyleft, littéralement copie laissée (pour "droits abandonnés" , jeux de mot anglais entre right (droite) et left (gauche)), qui consiste à détourner le principe du copyright (ou droit d'auteur) pour préserver la liberté d'utiliser, d'étudier, de modifier et de diffuser le logiciel et ses versions dérivées.
La GPL est la licence de logiciel libre la plus utilisée. En avril 2004, 74,6% des 23 479 projets libres présents sur le site Freshmeat et 68.5% des 52 183 projets libres présents sur SourceForge étaient publiés sous licence GPL.
La GNU GPL a une licence soeur, la LGPL (GNU Lesser General Public License et plus anciennement GNU Library General Public License), une version modifiée pour être moins contraignante quant son utilisation dans un contexte de cohabitation avec des logiciels propriétaires. Elle a une autre licence soeur, la GFDL (GNU Free Documentation License) qui, elle, est applicable aux manuels, livres ou autres documents écrits. Cette dernière présente toutefois des inconvénients, mis en avant par le projet Debian; on peut choisir à sa place la GPL, qui est tout fait applicable à un livre, article de carnet Web ou autre création.
4.1.2) Logiciels gratuits: graticiels
Un graticiel (freeware) est un logiciel mis gratuitement à disposition par son créateur soit en tant que logiciel libre, soit en tant que logiciel propriétaire, auquel cas il est soumis à certaines contraintes quant à sa diffusion. Les graticiels ne doivent pas être confondus avec les logiciels commerciaux diffusés de manière bridée en termes de fonctionnalités (dit de démonstration), ou en termes de durée d'utilisation (partagiciel, shareware en anglais). Ils sont parfois financés par la publicité qu'ils contiennent.
4.2) Filtres et utilitaires
Filtres et utilitaires:
head et tail
wc
cut
tee
sort
Les filtres sont des utilitaires standards, présents sur tous les systèmes Unix.
Ils permettent de multiples traitements sur les fichiers de texte (organisés en lignes) et constituent des outils très intéressants, aussi bien pour le développeur que pour l'utilisateur.
Leur appellation provient du fait qu'ils apparaissent assez souvent dans des "pipelines" pour mettre en forme des résultats de commandes.
Ces résultats sont écrits sur la sortie standard. On utilise des redirections pour les archiver dans des fichiers.
4.3) Quelques filtres simples
4.3.1) La commande head
La commande head affiche les premières lignes d'un fichier.
head [-n] [fichier] avec -n le nombre de lignes souhaitées (par défaut 10).
Remarque: on peut aussi demander à afficher les lignes 2 à n, dans ce cas utiliser tail -n+2 fichier
4.3.2) La commande tail
La commande tail permet d'afficher les dernières lignes d'un fichier.
tail [ +/-[n] [l|b|c] ] [-f] [fichier]
+n | Affichage à partir de la ligne de numéro n |
-n | Affichage des n dernières lignes (défaut 10) |
l | n est exprimé en lignes (défaut) |
b | n est exprimé en blocs de 512 octets |
c | n est exprimé en caractères |
f | Attente de nouvelles lignes (sortie par BREAK) |
4.3.3) La commande wc (word count)
La commande wc permet de compter les lignes, mots et caractères d'un fichier.
wc [ -lwc ] fichier
-l | nombre de lignes. |
-w | nombre de mots. |
-c | nombre de caractères. |
4.3.4) La commande cut
La commande cut permet de sélectionner des caractères ou des mots dans une ligne.
cut -fliste [-dsep] [-s] [fichier ... ]
cut -cliste [fichier ... ]
liste | n-m ou n,m ou -m (à partir du début de ligne) ou m- (jusqu'à la fin de la ligne) |
-c | Sélection de caractères |
-f | Sélection de mots |
-dsep | Redéfinition du séparateur |
-s | Suppression des lignes sans séparateurs |
4.3.5 La commande tee
La commande tee permet de mémoriser les résultats intermédiaires dans le fichier donné en argument. Par exemple mémoriser la sortie standard permet de stocker le résultat et le voir à l'écran).
tee [-a] fichier
-a | permet une utilisation en mode" ajout" |
Quelques exemples:
$ls -la | tail +2
$ head -15 exemple | tail +10
$ ls | wc -1
$ ls | wc -l | tee liste
$wc -lc exemple
$cut -d: -f 1,3,6,7 /etc/passwd
$cut -c1-9,64- exemple
4.3.6) Utilitaire de tri: sort
sort [options] [ -k keydef] [ -o fichier] [ - tcar ] fichiers ...
L'unité de traitement est la ligne ou le mot ( champ ).
Le critère de tri par défaut est l'ordre ascii.
De multiples options permettent de choisir des critères plus réalistes (alphabétique, numérique ... ).
Si aucun fichier n'est donné en argument ou si on utilise le caractère - (signe moins), la commande traite son entrée standard.
Le résultat du tri est écrit sur la sortie standard.
Quelques options:
-b | Pour une bonne gestion du nombre variable d'espaces ou de tabulations entre les champs (option quasiment indispensable pour des tris alphabétiques) |
-d | Seuls les lettres, chiffres, espaces et tabulations sont significatifs pour le tri |
-f | Minuscules et MAJUSCULES sont confondues |
-n | Tri numérique (pour trier en fonction de la tailel du fichier) |
-r | Résultat en ordre décroissant |
-u | Suppression de lignes multiples dans le résultat |
-o fichier | Sauvegarde du résultat dans le fichier spécifié (Ce fichier peut être un des fichiers d'entrée) |
-tcar | Redéfinition du caractère séparateur |
4.3.7) Utilisation des champs
La notation -k keydef permet d'indiquer que le tri doit s'effectuer uniquement sur certains champs de la ligne.
Il est possible d'indiquer plusieurs couples de clés pour opérer un tri à plusieurs passes.
Ces clés s'expriment sous la forme [ début [type] [,fin [type]]
début ,fin Portion de ligne à traiter en indiquant les Numéros du champ
type Une ou plusieurs options parmi b, d, f, i, n ou r. Le type b, s'il est positionné, s'applique sur le champ souhaité en plus de l'option b.
Quelques exemples:
$ sort -k2,2 fic
Tri (critère Ascii) sur le deuxième champ du fichier fic.
$ sort -bf -k2,2 fic
Tri alphabétique sur le deuxième champ.
Ignorer le nombre d'espaces avant et après le champ.
$ sort -t: -rn -o fichier.out -k3,3 fic
Tri (critère numérique, ordre décroissant) sur le troisième champ avec redéfinition du séparateur de champs.
Sauvegarde du résultat dans le fichier fichier.out.
4.4) Transformations de caractères: tr
tr [options] [ chaînel [ chaîne2 ] ]
Ce filtre lit l'entrée standard pour effectuer des substitutions ou des suppressions de caractères. Les résultats sont écrits sur la sortie standard.
Dans la syntaxe de base, les caractères mentionnés dans "chaîne1" sont remplacés par ceux de même position dans "chaîne2".
Des abréviations sont possibles pour désigner des ensembles de caractères:
Notation | Description |
---|---|
[a- z] | Les lettres minuscules (intervalle) |
[a*n] | n fois le caractère a (* seul signifie "un nombre quelconque") |
\xyz | Code Ascii en octal du caractère |
[ :class: ] | Indique une classe de caractères :lower: :upper: :alpha: :alnum: :digit: :space : |
Notation | Description |
---|---|
-d | Supprimer les caractères apparaissant dans "chaine1" |
-s | Les caractères consécutifs identiques sont réduits à un seul exemplaire |
-c | Négation -> Les caractères n'apparaissant pas dans "chaine1" |
4.5) Rappel sur les expressions régulières
Expressions régulières et grep
Ensemble de caractères spéciaux
Utilisation de grep
Les expressions régulières forment un langage de description d'ensembles de chaînes de caractères. Parmi les différents utilitaires UNIX utilisant la notion d'expressions régulières, citons ex (appelé depuis le mode de commandes syntaxique de vi ), les filtres awk/nawk, grep, sed. Voici une liste des caractères spéciaux les plus employés dans les expressions régulières:
Caractère | Description |
---|---|
^ | Début de ligne |
$ | Fin de ligne |
. | Présence d'un caractère quelconque |
[caractères] | Un caractère parmi un ensemble donné |
[^caractères] | Un caractère ne figurant pas dans l'ensemble |
* | Un nombre quelconque d'apparitions d'un caractère (éventuellement aucune apparition) |
\ | Annuler la sémantique d'un caractère dans l'expression |
Caractère | Description |
---|---|
+ | Début de ligne |
? | Fin de ligne |
() | Présence d'un caractère quelconque |
| | Un caractère parmi un ensemble donné |
Caractère | Description |
---|---|
^[abc] | a b ou c en début de ligne |
^[^abc] | tout caractère sauf a b et c en début de chaîne. |
^[^^]) | tout caractère autre que ` en début de chaîne. |
ab?c | ac ou abc. |
(ab)+c | abc ou ababc ou abababc etc. |
^ab|cde *$ | ab en début de chaîne ou cde suivi d'espaces éventuels en fin de chaîne. |
^[0-9] +$ | chaîne constituée uniquement de chiffres. |
4.6) Recherche d'expressions avec grep
Ce filtre permet de rechercher des expressions littérales ou "régulières" dans des fichiers. Les lignes comportant les expressions recherchées sont affichées sur la sortie standard. Le filtre grep présenté ici est celui conforme au guide XPG4. Sur de nombreuses versions d'UNIX, le grep par défaut est une ancienne version qui ne sait pas utiliser les expressions régulières enrichies. Syntaxe: grep [-E -F] [-c J -1 J -q] [options] expr fichiers ... ou grep [-E -F] [-cJ-1J-q] [options] [ -e expr ... ] [ -f fichier ... ] fichiers .. Quelques Options:-E | L'expression est traitée comme expression régulière enrichie (anciennement egrep). |
-F | L'expression est traitée comme expression littérale (anciennement fgrep). |
-c | Afficher le nombre de lignes trouvées |
-l | Afficher uniquement les noms des fichiers |
-q | Supprime l'affichage des lignes résultat |
-i | MAJUSCULES et minuscules sont confondues |
-n | Chaque ligne est précédée de son numéro dans le fichier |
-v | Les lignes ne comportant pas l'expression |
-x | Les lignes exactement identiques à l'expression |
-e expr | Permet de chercher plusieurs expressions. Permet aussi de chercher une expression commenant par - (signe moins) |
-f fichier | Les expressions cherchées sont décrites dans un fichier (une par ligne) |
^$ | Ligne vide (un début et une fin). |
. | Ligne non vide. |
.* | "Reste de la ligne" ou "ligne complète" suivant le contexte. |
4.7) La commande getopts
La commande getopts Analyse des options Un format" Unix"
L'un des problèmes lors de l'écriture d'un script est l'analyse syntaxique des options pouvant être passées à un programme. Il faut tenir compte des différentes possibilités d'utilisation du script (par exemple -ab, -ba, -b -a etc.).
La comande getopts vous facilite le travail. Vous lui dites quelles sont les options, y compris celles qui ont des arguments. Elle fait pour vous l'analyse syntaxique et permet à l'utilisateur d'indiquer ces options avec la même souplesse que dans les commandes de base.
La syntaxe de base est la suivante :
getopts [:]lettre[:] ... VARIABLE [ARGUMENTS ... ]
Le symbole : qui peut précéder les lettres indique que vous gérez vous même le cas des options incorrectes.
La commande procède sinon un traitement par défaut.
Chaque lettre désigne l'une des options autorisées dans la ligne de commande sous la forme -lettre.
Le symbole: qui peut suivre une lettre signifie que l'option attend un argument. Cet argument sera dans la variable pré définie OPTARG. VARIABLE désigne la variable dans laquelle getops met l'option rencontrée votre disposition.
ARGUMENTS désigne la chaîne des arguments, $* par défaut.
getopts renvoie 0 (vrai) pour signifier qu'elle a trouvé une option. On utilise donc getopts en conjonction avec une boucle while ou un case.
Voici un exemple d'utilisation de getopts.
#!/bin/ksh # # Exemple d'utilisation de getopts # # ./getoptsl.ksh -avf fichier # # # -a : Option a # -v : Option v # -f fichier : Option f avec un fichier en argument # # flaga=O flagv=O flagf=O while getopts af:v option do case $option in a) flaga=1 ;; f) flagf=1 fichier=$OPTARG ;; v) flagv=1 ;; esac done if [ $flaga -eq 1 ] then echo "Option a activee." fi if [ $flagv -eq 1 ] then echo "Option v activee." fi if [ $flagf -eq 1 ] then echo "Option f activee. Operation sur le fichier $fichier" fi exit 0
$ ./getoptsl.ksh -avf fichier1 Option a activee. Option v activee. Option f activee. Operation sur le fichier fichier1
Chapitre 5: sed & awk
Objectifs: Utilisation de awk et de nawk
Utilisation de sed
5.1) Edition (non interactive) de fichiers: sed
Utilisation de sed: Edition non-intéractive.
Utilise les mêmes commandes que vi.
Ce filtre est un éditeur non interactif qui copie les fichiers d'entrée sur la sortie standard après leur avoir appliqué un certain nombre de commandes.
Syntaxe:
sed [-n] 'commandes_sed' fichiers ... ou sed [-n] -f fichier_commandes fichiers ...
5.1.1) Syntaxe des commandes sed et principe de fonctionnement
[ adresse1[,adresse2] ] action [arguments]
Les crochets indiquent un aspect facultatif et n'apparaissent pas dans les commandes.
Tous ces éléments ne sont séparés par aucun espace.
En l'absence d'adresses de sélection, l'action a lieu sur toutes les lignes des fichiers en entrée.
L'action par défaut est d'afficher la ligne sur la sortie standard.
L'option -n permet de supprimer cette sortie systématique des lignes.
Une adresse peut être:
Un numéro de ligne
Le caractère $ désignant la dernière ligne
Une expression littérale ou régulière entre deux caractères /
Quelques actions usuelles:
d: Ne pas afficher la ligne.
p: Afficher la ligne (s'utilise souvent avec l'option -n).
q: Abandonner le traitement.
s/expr1/expr2/: Remplacer la première expression par la seconde..une seule fois par ligne.
s/expr1/expr2/g: Remplacer la première expression par la seconde..plusieurs fois par ligne si nécessaire.
s/exprl//: Supprimer l'expression.
s/exprl/...&.../: Expanser la première expression (elle-même + "quelque chose").( La notation & signifie "reprendre la première expression").
=: Afficher le numéro de ligne.
Remarque:
Pour écraser un fichier fic après avoir appliqué des commandes, on est obligé de faire ceci:
sed -f fichier_commandes fic>tmp
mv tmp > fic
Quelques exemples:
$ sed 's/monsieur/madame/g' fichier Remplacer une chaîne par une autre plusieurs fois par ligne
$ sed 's/^/ /' fichier Décaler le début de chaque ligne d'une espace.
$ sed '/./s/^/' fichier Idem uniquement sur les lignes non vides
$ sed -n '/expression/!p' fichier Afficher les lignes ne contenant pas l'expression ( Le! indique la négation de l'expression)
$ sed -n '20,30p' fichier Afficher les lignes de numéro 20 à 30
$ sed '1,10d' fichier Ne pas afficher les 10 premières lignes
$ sed -n '/./p' fichier Afficher uniquement les lignes non vides
$ sed '/^$/d' fichier Même traitement
$ sed '/expression/q' fichier Afficher jusqu'à trouver une expression donnée
$ sed -n '/expression/=' fichier Afficher les numéros des lignes contenant une expression donnée.
$ sed 's/[0-9] [0-9] */(&)/g' fichier Mettre entre parenthèses les nombres entiers plusieurs fois par ligne si nécessaire
Remarque: g pour le faire plusieurs fois.
5.2) Introduction au langage awk
Cet utilitaire awk tire son nom de ceux de ses concepteurs (Alfred AHO, Peter WEINBERGER, Brian KERNIGHAN qui est aussi l'inventeur du langage C).C'est un outil très adapté pour réaliser des tâches de manipulation de données sans avoir à les programmer dans un langage classique comme le C.
En effet, beaucoup de choses sont implicitement résolues (les entrées, la gestion des "champs", la gestion mémoire, les déclarations, les initialisations...).
5.2.1) Syntaxe et principe de fonctionnement
syntaxe:
awk -f fichier commandes fichiers ... ou awk 'liste-de-commandes' fichiers ...
Une commande est constituée ainsi: motif { action }
Le motif sert d'expression de sélection des lignes pour y appliquer l'action associée.
Si le motif est absent, toutes les lignes sont concernées par l'action. L'action par défaut consiste à afficher la ligne.
Chaque ligne d'entrée est automatiquement divisée en champs. Les différents champs sont nommés respectivement: $1 $2 $3 ... $NF
NF représente le nombre de champs de la ligne en cours de traitement.
Le séparateur de champs peut être positionné à un caractère particulier. Pour ce faire, on peut procéder de deux façons:
1) On utilise comme première commande : BEGIN { FS = "caractère" }
ou
2) A l'appel de "awk", on utilise l'option -Fcaractère
D'autres variables intéressantes sont pré définies:
$0 La ligne entière.
NR Numéro de la ligne courante.
FILENAME Nom du fichier courant d'entrée.
5.2.2) Les motifs
Les programmes peuvent souvent se résumer à une suite de motifs puisque l'action par défaut est l'impression des lignes sélectionnées.
"awk" est donc un outil très puissant de sélection.
Quelques motifs possibles:
- Expression bâtie avec des opérateurs très proches de ceux du langage C:
$3 < 10
$3 < $2 + 10 && $4 == "dupont"
- Expression littérale ou régulière entre deux caractères / :
/dupont/
/^[0-9]/
- Intervalle de numéros de lignes
NR == 10 , NR == 15
- Le motif BEGIN
L'action associée est exécutée avant le traitement des fichiers d'entrée
- Le motif END
L'action associée est exécutée après le traitement des fichiers d'entrée
5.2.3) Les actions
Une action est une suite d'instructions. Chaque instruction est terminée par un; ( point-virgule) ou un saut de ligne. Instructions disponibles Les fonctions d'affichage print ( affichage brut) et printf ( affichage formaté ) Instruction bâtie avec des opérateurs très proches de ceux du langage C Instructions de contrôle ( tests, boucles, fonctions intégrées ... Quelques exemples : $ awk ' $3 >1000 { print $1 , $2 , $3 } , fichier Pour toutes les lignes où le troisième champ est supérieur à mille, on affiche la valeur des trois premiers champs. $ awk ' { print NR , $0 } , fichier Numéroter les lignes d'un fichier. $ awk ' { printf "%4d %s\n" , NR , $0 } , fichier Même traitement avec formatage. $ awk '$3 > 1000 { va1++ } END { print val }, fichier Afficher le nombre de lignes où le troisième champ est supérieur à 1000. $ awk '$3 > max {max = $3; maxnom = $2 } END { print max , maxnom J' fichier Afficher la valeur maximum du troisième champ ainsi que celle du deuxième champ associé. $ awk ' { noms = noms $2 Il " } END { print noms }, fichier Afficher la concaténation de tous les deuxièmes champs ( Concaténation par juxtaposition) $ awk 'BEGIN { printf "Calcul du maximum et de la moyenne\n"} { somme += $3 } $3 >max { max = $3 } END { printf "Maximum = %lO.2f Moyenne } %lO.2f\n", max, somme/NR , fichier
5.2.4) Les tableaux associatifs
On peut manipuler des tableaux de couples" clé = valeur" ( clé unique). En général, cette clé prend toutes les valeurs possibles d'un des champs du fichier traité. Contenu du fichier" exemple" roger martin 12000 cd1 rene duva1 500 cd1 marie pervenche 12010 cd3 Marcel dupond 600 cd2 paul martin 10000 cd4 roger martin 12500 cd1 Rene DUVAL 510 cd1 marie pervenche 13000 cd3 marie martin 13000 cd3 Sophie Martinez 6512 cd2 Sylvie Martinelli 45678 cd2 Paul Legrand 4560 cd5 michel DUVAL 54500 cd1 Mireille Duvalier 12345 cd2 Paul LEGRAND 14560 cd5 Rene Pervenche 5400 cd3 Paul martinez 5600 cd2 Andre dupond 650 cd5 Soit le fichier prog contenant les instructions suivantes BEGIN {printf "EXEMPLE DE TABLEAU ASSOCIATIF\n" } {tab($2] += $3} {for (nom in tab) printf "%-20s %6d\n" , nom, tab(nom] } END On construit dynamiquement un tableau associatif" tab" dont les indices (clés) sont toutes les valeurs possibles du deuxième champ. Pour une clé donnée, la valeur associée consiste à faire la somme des valeurs du troisième champ. On obtient à l'exécution $ awk -f prog exemple EXEMPLE DE TABLEAU ASSOCIATIF dupond 1250 Legrand 4560 martin 47500 LEGRAND 14560 pervenche 25010 martinez 5600 Pervenche 5400 Duvalier 12345 DUVAL 55010 duval 500 Martinelli 45678 Martinez 6512
5.2.5) Aide-mémoire résumé de awk
Variables prédéfinies Variable Nombre d'arguments de la ligne de commande. Description ARGC ARGV Tableau contenant les arguments de la ligne de commande. FILENAME Numéro d'enregistrement dans le fichier courant. Nom du fichier d'entrée courant. FNR FS Séparateur de champs en entrée (" espace" par défaut). Nombre d'enregistrements lus jusqu'à présent. NF Nombre de champs dans l'enregistrement courant. OFMT NR Format d'affichage pour les nombres ("%. 6g" par défaut). OFS Séparateur de champs à l'affichage ("espace" par défaut). Séparateur d'enregistrements à l'affichage (" \n" par défaut). ORS RLENGTH Longueur de la concordance obtenue par la fonction "match" . RS Séparateur d'enregistrements en entrée (" \n" par défaut). Première position dans la chaîne qui concorde avec la fonction "match". RSTART Opérateurs = += -= *= Affectation. Opérateurs /= %= ,.. Description ? : Ou logique. Si Alors Sinon. Il &:&: ET logique. Opérateurs de comparaison. Concordance ( ou non) avec une expression régulière. < <= > >=! = Multiplication, division, modulo. + - Addition, soustraction. Plus unaire, moins unaire, NON logique. * / % ~ ( ou ** ) Puissance. + -! ++ -- Incrémentation et décrémentation. Instructions de contrôle if ( expression ) instruction if ( expression ) instructionl else instruction2 while ( expression ) instruction for ( expressionl; expression2; expression3 instruction for ( variable in tableau ) instruction do instruction while ( expression ) break continue next exit expression
5.2.6) Quelques fonctions intégrées
Fonction atan2 x, y ) cos X ) exp x ) int x ) log x ) rand ( ) sin ( x ) sqrt x gsub ( r 1 s 1 t ) Description Arctangente Cosinus. Exponentielle. Partie entière. Logarithme. Nombre aléatoire dans l'intervalle [0,1]. Sinus. Racine carrée. Remplace globalement par s chaque occurrence de r dans la chaîne t. ( $ 0 par défaut ). Retourne le nombre de remplacements effectués. index ( s 1 t Première position de t dans s. length ( s ) Longueur de la chaîne. match ( sir Position de la sous-chaîne en concordance avec l'expression r. Mise à jour des variables RSTART et RLENGTH. split ( s 1 t 1 sc ) Décomposition de s en un tableau t selon le séparateur sc. ( FS est le séparateur par défaut ). sub ( r,s 1 t Remplace par s la première occurrence de r dans la chaîne t. substr s 1 i 1 n Sous-chaîne de longueur n de s débutant en position i. system commande) Exécution d'une commande. getline Lecture de données via l'entrée standard, un fichier ou un "pipe". getline getline var getline
Annexe A: Enoncé des exercices
A.1) TP DE PROGRAMMATION SHELL
TP1) Traitement de la ligne de commandes et utilisation de la commande test sur les fichiers
- Ecrire un script tp1.ksh qui reçoit un fichier en argument
- Le script vérifie qu'un argument est passé sur la ligne de commandes
- Si c'est un répertoire, le script liste son contenu avec ls
- S'il s'agit d'un fichier ordinaire "texte", le script l'affiche en mode paginé avec more
Appel: $ ./tpl.ksh fichier
TP1-bis) Traitement de la ligne de commandes et utilisation de la commande test sur les fichiers
- Idem TP1, avec le test en syntaxe Korn Shell
- Le nom du script est tp1bis.ksh
Appel: $ ./tplbis.ksh fichier
TP2) Exemple de boucle for
Ecrire un script tp2. ksh qui liste dans une boucle for les commandes d'un répertoire donné en argument.
S'il n'y a aucun argument, le script traite le répertoire courant.
Note: Une commande est un fichier ordinaire et exécutable.
Appel: $ ./tp2.ksh [ fichier]
TP2-bis) Exemple de boucle for et d'utilisation des expressions arithmétiques
Idem TP2, avec le comptage du nombre de commandes situées dans le répertoire. Le nom du script est tp2bis.ksh.
Appel: $ ./tp2bis.ksh [ fichier ]
TP3 Exemple de boucle while et de lecture clavier
Ecrire un script tp3.ksh qui affiche un message au terminal à une heure donnée. Il récupère l'heure du système sous la forme hh:mm.
Il réalise la lecture au clavier d'une heure au même format hh:mm.
Il vérifie dans le cas d'une saisie non vide que l'heure est postérieure sinon il quitte le programme.
Dans une boucle while, le script attend cette heure en recalculant l'heure système toutes les 10 secondes pour afficher un message au terminal de l'utilisateur.
Note: Penser à utiliser la commande date avec le format suivant: date +%H :%M
Appel: $ /tp3.ksh
TP4 Exemple d'aiguillage case
Ecrire un script tp4.ksh qui reçoit deux noms de fichiers fic1 et fic2 en arguments.
Le traitement est une boucle sur la lecture des informations au clavier.
La fin de la boucle a lieu sur saisie vide.
À l'aide de l'aiguillage case, les lignes ne comportant que des lettres sont ajoutées dans le fichier fic1, les lignes ne comportant que des chiffres sont ajoutées dans le fichier fic2. Les autres lignes sont rejetées.
Le script affichera le nombre de lignes pour les trois cas en fin de traitement. Appel: $ ./tp4.ksh fic1 fic2
TP 5 Instruction select , Expressions arithmétiques et tableaux
Ecrire un script tp5.ksh qui réalise une opération sur 2 entiers
Les opérations suivantes sont disponibles: Addition, Soustraction, Division, Multiplication
La structure select du Korn Shell est utilisée pour valider le type d'opération souhaitée, afficher la liste des toutes ces opérations et sortir du script.
Après saisie des 2 entiers, le script vérifie que les nombres sont des entiers et réalise l'opération demandée par l'utilisateur.
Appel: $ ./tp5.ksh
Un plus dans le script est de prévoir l'opération Modulo Appel: $ ./tp5bis.ksh
TP6 Exemple de traitement des interruptions, utilisation des fonctions et de la boucle while
Ecrire un script tp6. ksh qui réalise dans une boucle infinie while la création puis le grossissement d'un fichier par la redirection d'un message dans le fichier.
Le script intercepte les signaux INT, QUIT et TERM comme suit:
- Ignore le signal QUIT ( 3 )
- Sur réception du signal INT ( 2 ) ou TERM ( 15), appelle une fonction de déroutement qui supprime le fichier
Appel: $ /tp6.ksh
A.2 ENONCES D'EXERCICES SUR LES FILTRES
Dans la suite la référence au fichier" exemple" est faite à partir du contenu vu ci-dessous:
roger martin 12000 cd1
rene duva1 500 cd1
marie pervenche 12010 cd3
Marcel dupond 600 cd2
paul martin 10000 cd4
rager martin 12500 cd1
Rene DUVAL 510 cd1
marie pervenche 13000 cd3
marie martin 13000 cd3
Sophie Martinez 6512 cd2
Sylvie Martinelli 45678 cd2
Paul Legrand 4560 cd5
michel DUVAL 54500 cd1
Mireille Duvalier 12345 cd2
Paul LEGRAND 14560 cd5
Rene Pervenche 5400 cd3
Paul martinez 5600 cd2
Andre dupond 650 cd5
Exercice 1 Utilitaire de tri sort sur le fichier exemple
1) Trier sur le troisième champ en ordre décroissant 2) Trier sur le deuxième champ ( minuscules et majuscules confondues) 3) Trier sur le deuxième champ ( minuscules et majuscules confondues) puis deuxième passage sur le premier champ ( même critère) puis troisième passage sur le troisième champ
4) Trier sur les trois premiers caractères du deuxième champ (critère code ascii)
Exercice 2 Utilitaire de tri sort sur des commandes ou fichiers du système
1) Trier le résultat de "ls - al" d'après la taille des fichiers
2) Trier le fichier /etc/passwd d'après le numéro de login (UID) en ordre décroissant
Exercice 3 Transformation de caractères tr en sortie de commande ls
1) Afficher la liste des fichiers du répertoire courant en majuscules
2) Remplacer, dans le résultat de "ls -al", tout caractère n'étant ni un chiffre, ni un espace, ni un saut de ligne par la lettre X.
Exercice 4 Recherche d'expressions avec grep sur le fichier exemple
1) Rechercher les lignes du fichier "exemple" qui commencent par m ou M.
2) Rechercher les lignes du fichier" exemple" qui comportent la lettre a en deuxième position.
3) Rechercher les lignes du fichier" exemple" qui se terminent par 1 ou 2.
4) Rechercher les lignes du fichier" exemple" qui commencent par une majuscule OU qui se terminent par la chaîne "cd1".
5) Rechercher les lignes du fichier" exemple" qui commencent par une majuscule ET qui se terminent par la chaîne "cd2" (avec le résultat trié sur le troisième champ en ordre décroissant ).
Exercice 5 Recherche d'expressions avec grep sur le fichier /etc/passwd
1) Dans le fichier /etc/passwd, rechercher les lignes correspondant aux utilisateurs du Korn-shell.
2) Même question pour les utilisateurs potentiels du Bourne-shell.
Exercice 6 Edition non interactive de fichiers sed sur le fichier exemple
1) Dans les lignes du fichier" exemple" qui ne contiennent pas la chaîne "cd1", remplacer la chaîne "cd" par la chaîne "code".
2) Afficher le fichier "exemple" jusqu'à trouver la chaîne "cd5" (ligne non comprise).
3) Décaler, de quelques espaces, le début des lignes du fichier "exemple" commençant par une majuscule
4) Mettre des parenthèses autour des lignes du fichier "exemple" qui se terminent par "cd1"
5) Idem "question 4" mais en n'affichant que les lignes modifiées, triées sur le deuxième champ (minuscules et majuscules confondues) avec une deuxième passe sur le troisième champ en ordre décroissant
6) Remplacer tous les "0" du fichier exemple par des "x" et tous les "1" par des "y"
Exercice 7 Traîtement sur le fichier exemple avec l'outil awk
1) Afficher le fichier en numérotant les lignes et en permutant les deux premières colonnes.
2) Afficher noms et prénoms des personnes correspondant aux codes "cd1"ou "cd2".
Afficher en final le nombre de ces personnes.
3) Afficher la ligne pour laquelle le nombre (3ème colonne) est le plus grand.
4) Pour chaque code, afficher le total des nombres (3ème colonne).
Afficher en final la moyenne des nombres.
A.3 ENONCES D'EXERCICES DE L'ATELIER DE PROGRAMMATION SHELL
Les ateliers ci-dessous ne sont pas proposés dans un ordre croissant de difficulté. On peut donc les aborder dans un ordre quelconque selon leur thème respectif ou selon ses préférences personnelles.
Atelier 1 Modification de nom de fichiers avec confirmation éventuelle et gestion de la ligne de commandes
Ecrire un script atelier1.ksh qui recoit deux arguments .ext1 et .ext2.
Le but du script est de renommer tous les fichiers d'extension. ext1 du répertoire courant en * . ext2.
Le script vérifiera que les arguments sont des "extensions:" ." suivi de l'extension en minuscules.
Si on donne l'option " -i ", le script propose la confirmation pour chaque fichier.
Note : Penser à utiliser la commande basename sur les noms de fichiers à traiter
Syntaxe: $ basename string [suffix]
Appel: $ atelier1.ksh [ -i ] .ext1 .ext2
Atelier 2 Autre script de modification de nom de fichiers
Ecrire un script atelier2.ksh qui recoit des noms de fichiers en arguments.
Pour chaque argument, s'il s'agit d'un fichier ordinaire dont le nom ne contient que des MAJUSCULES, on le renomme en minuscules.
Appel: $ atelier2.ksh liste_fichiers
Atelier 3 Traitements sur les fichiers : test
Ecrire un script atelier3 .ksh qui recoit des noms de fichiers en arguments.
Si le fichier existe et est un fichier ordinaire, on affiche sa taille.
Si le fichier n'existe pas, on le créée de taille O.
Si l'option "-c" est utilisée, le script ne créée pas le fichier s'il n'existe pas.
Appel: $ atelier3.ksh [ -c ] liste_fichiers
Atelier 4 Menu simple avec case et appel de commandes UNIX
Ecrire un script atelier4. ksh sous la forme d'un menu dans une boucle until. Le script prévoit avec la structure case:
- 1. L'affichage de l'heure
- 2. Le changement de répertoire courant
- 3. La sauvegarde au format tar compressé des fichiers ordinaires du répertoire courant après avoir vérifié qu'il y en a Après saisie du nom de l'archive souhaité, la création de celle-ci se fait sous /tmp
- 4. La liste du contenu d'une archive dont on saisit le nom
- 5. La Restauration interactive de fichiers d'une archive
- 6. 0 La Sortie
Rappel sur la syntaxe de tar:
Création d'une archive: tar -cvf fichier_archive liste_a_sauvegarder Lecture d'une archive: tar -tvf fichier_archive Imore Restauration d'une archive: tar -xvf fichier_archive liste_a_restaurer Appel: $ atelier4.ksh
Atelier 5 Gestion de la ligne de commande et traitement sur les fichiers
Ecrire un script atelier5.ksh qui reçoit en premier argument un entier puis une liste de fichiers.
Le script vérifie que le premier argument est un entier.
Il affiche pour chaque fichier les lignes plus longues que cette valeur et le nombre de lignes.
Appel: $ atelier5.ksh valeur liste_fichiers
Atelier 6 Traitements sur les fichiers et Expressions arithmétiques Ecrire un script atelier6. ksh qui reçoit une liste de noms de fichiers en arguments.
Le script ne conserve de la liste d'arguments que les fichiers ordinaires et affiche la taille en octets de chacun, la taille totale ainsi que le nom du plus gros fichier.
Appel: $ atelier6.ksh liste_fichiers
Atelier 7 Habillage de la commande find et utilisation de fonctions
Le script atelier7.ksh propose par menu d'utiliser la commande find.
Les critères suivants sont proposés:
- nom Le script appelle l'option -name de find.
- proprietaire Le script appelle l'option -user de find. Le script vérifie qu'on donne un "login" existant
- dates Le script propose dans un sous-menu l'une des options de find suivantes: -mtime, -atime ou -newer
Pour chaque critère, le script fait la saisie au clavier de l'argument correspondant à l'option choisie.
Le script affiche la commande correspondant aux choix de l'utilisateur.
Celle-ci est lancée après confirmation de l'utilisateur.
Le script permet d'interrompre l'exécution de la commande find sans quitter le programme complet.
Appel: $ atelier7.ksh
Atelier 8 Traitement de la ligne de commande
Ecrire un script atelierS. ksh qui traite la ligne de commande de la façon suivante:
Si on a saisi "-u user" Le script affiche le nom des groupes de "user"
après vérification qu'il s'agit d'un "user" existant.
Sans l'option, il affiche ses propres groupes.
- "- t" Le script affiche le type de terminal de connexion.
S'il y a des arguments, le script les affiche tels quels.
Note: Il est possible d'utiliser getopts
Appel: $ atelier8.ksh [ -u user] [ -t ]
Annexe B: Corrections des exercices
B.1 CORRIGES DE TP PROGRAMMATION SHELL
TP1 Traitement de la ligne de commandes et utilisation de la commande test sur les fichiers
- Ecrire un script tp1.ksh qui reçoit un fichier en argument
- Le script vérifie qu'un argument est passé sur la ligne de commandes
- Si c'est un répertoire, le script liste son contenu avec ls
- S'il s'agit d'un fichier ordinaire "texte", le script l'affiche en mode paginé avec more
#!/bin/ksh # # tp1. ksh # # Appel: ./tp1.ksh fichier # # Auteur : JM Lacoste # # ################################################################################ ### Verifier qu'un seul argument est passe et le placer dans la variable FICHIER if [ $# != 1 ] then echo "Usage : $0 fichier" echo "Au revoir" exit 1 else FICHIER=$1 fi ### Tester si c'est un repertoire alors 1s if [ -d $FICHIER ] then echo "$FICHIER est un repertoire" echo "Liste du contenu de $FICHIER" echo "****************************************************" 1s $FICHIER fi ### Tester si c'est un fichier simple alors more if [ -f $FICHIER ] then more $FICHIER fi exit 0
TP1-bis Traitement de la ligne de commandes et utilisation de la commande test sur les fichiers
- Idem TP1, avec le test en syntaxe Korn Shell
- Le nom du script est tp1bis.ksh
#!/bin/ksh # # tplbis.ksh # # Appel: ./tplbis.ksh fichier # # # # ################################################################################ ### Verifier qu'un seul argument est passe et le placer dans la variable FICHIER if [[ $# == 1 ]] then FICHIER=$1 else echo "Usage : $0 fichier" echo "Au revoir" exit 1 fi ### Tester si c'est un repertoire alors 1s if [[ -d $FICHIER ]] then echo "$FICHIER est un repertoire" echo "Liste du contenu de $FICHIER" echo "********************************************************" ls $FICHIER fi ### Tester si c'est un fichier simple alors more if [[ -f $FICHIER ]] then more $FICHIER fi exit 0
TP2 Exemple de boucle for
Ecrire un script tp2.ksh qui liste dans une boucle for les commandes d'un répertoire donné en argument.
S'il n'y a aucun argument, le scripte traite le répertoire courant.
Note: Une commande est un fichier ordinaire et exécutable
Appel: $ . / tp2.ksh [ fichier ]
#!/bin/ksh # # tp2.ksh # # Appel: ./tp2.ksh [ repertoire ] # # # # ################################################################################ ### Verifier le nombre d'arguments case $# in 0) REP=$PWD 1) if [ -d $1 ] then REP=$1 else echo "L'argument doit eCre un repertoire ... " echo " et $1 n'est pas un repertoire ... Au revoir ..." exit 2 fi ;; *) echo "Usage : $0 [ repertoire ]" echo "Au revoir" exit 1 ;; esac ### Boucler sur les elements contenus dans le repertoire ### En verifiant que ce sont des commandes executables (bit x). for i in `ls $REP` do if [ -x ${REP}/$i -a -f ${REP}/$i ] then printf "%-15s est une commande executable.\n" "${REP}/$i" fi done exit 0
TP2-bis Exemple de boucle for et d'utilisation des expressions arithmétiques
Idem TP2, avec le comptage du nombre de commandes situées dans le répertoire. Le nom du script est tp2bis.ksh.
Appel: $ . / tp2bis. ksh [ fichier ]
#!/bin/ksh # # tp2bis.ksh # # Appel: ./tp2bis.ksh [ repertoire ] # # # # ############################# ### Initialisation des variables NBEXEC=O ### Compteur d'executables ### Verifier le nombre d'arguments case $# in 0 ) REP=$PWD ;; 1 ) if [ -d $1 ] then REP=$1 else echo "L'argument doit etre un repertoire..." echo " et$1 n'est pas un repertoire... Au revoir..." exit 2 fi ;; * ) echo "Usage : $0 [ repertoire ]" echo "Au revoir" exit 1 ;; esac ### Boucler sur les elements contenus dans le repertoire ### En verifiant que ce sont des commandes executables (bit x). for i in `ls $REP` do if [ -x ${REP}/$i -a -f ${REP}/$i ] then printf "%-15s est une commande executable.\n" "${REP}/$i" NBEXEC=`expr $NBEXEC + 1` fi done echo "=================" echo " Il y a $NBEXEC executables dans le repertoire $REP" exit 0
TP3 Exemple de boucle while et de lecture clavier
Ecrire un script tp3.ksh qui affiche un message au terminal à une heure donnée. Il récupère l'heure du système sous la forme hh :mm.
Il réalise la lecture au clavier d'une heure au même format hh :mm.
Il vérifie dans le cas d'une saisie non vide que l'heure est postérieure sinon il quitte le programme.
Dans une boucle while, le script attend cette heure en recalculant l'heure système toutes les 10 secondes pour afficher un message au terminal de l'utilisateur.
Note : Penser à utiliser la commande date avec le format suivant date +%H :%M
Appel: $ ./tp3.ksh
#!/bin/ksh # # tp3.ksh # # Appel ./tp3.ksh # # # # ############################# HEURE='date +%H:%M' while true do echo "Il est 'date +%H:%M'" read clavier echo "clavier : $clavier" ### Comparer la reponse a l'heure systeme ### Si HeureSaisie <= HeureSys ok, sinon sortie if [ -z $clavier ] then echo "Au revoir." exit 0 else while [ "$HEURE" != "$clavier" ] do HEURE='date +%H:%M' echo $HEURE sleep 10 done fi banner "Et voila." done exit 0
TP4 Exemple d'aiguillage case
Ecrire un script tp4.ksh qui reçoit deux noms de fichiers fic1 et fic2 en arguments.
Le traitement est une boucle sur la lecture des informations au clavier.
La fin fin de la boucle a lieu sur saisie vide.
A l'aide de l'aiguillage case, les lignes ne comportant que des lettres sont ajoutées dans le fichier fiel, les lignes ne comportant que des chiffres sont ajoutées dans le fichier fic2. Les autres lignes sont rejetées Le script affichera le nombre de lignes pour les trois cas en fin de traitement. Appel: $ . / tp4 . ksh fiel fie2 Echo "Le fichier/rep $fic existe deja ... Au revoir .. exit 1 #!/bin/ksh # # tp4.ksh # # Appel: ./tp4.ksh fic1 fic2 # # # # ############################# ### Initialisation des variables ### Fonctions du programme function usage { Echo echo "Usage : $0 fic1 fic2" echo ### Tester qu'on a bien 2 arguments et que ce sont des fichiers inexistants, ### sinon sortir. if [ $# ! = 2 J then usage exit 1 fi for fic in $1 $2 do if [ -e /tmp/$fic then fi done FICA=/tmp/$l FICD=/tmp/$2 ### while true do read clavier case $clavier in + ( [a-zA-ZJ [a-zA-ZJ ) Echo "Un alpharr echo $clavier $FICA + ( [0-9J (O-9J) ) Echo I1Un digitll echo $clavier » $FICD
### Nettoyage rm $FICA $FICB echo "Au revoir ... " exit 0 ### Affichage des duex fichiers echo IIFichier des alphas" eche ,,===================11 cat $FICA echo "Fichier des digits" echo ,,========::::=========11 cat $FICD * ) esac done ### Pour une fois, cette clause ne peut pas etre atteinte. exit 0
TP 5 Instruction select , Expressions arithmétiques et tableaux
Ecrire un script tpS. ksh qui réalise une opération sur 2 entiers Les opérations suivantes sont disponibles : Addition, Soustraction, Division, Multiplication La structure select du Korn Shell est utilisée pour valider le type dopération souhaitée, afficher la liste des toutes ces opérations et sortir du script. Après saisie des 2 entiers, le script vérifie que les nombres sont des entiers et réalise l'opération demandée par l'utilisateur Appel: $ . /tp5. ksh 'expr $1 \. $2'" #!/bin/ksh # # tpS.ksh # # Appel: ./tpS.ksh # # # # ############################# ### Initialisation des variables typeset -i un typeset -i deux ### Fonctions du programme function add { echo "$1 + $2 ~ 'expr $1 + $2'" } function sub { echo "$1 - $2 } function mul { echo 11$1 . $2 } function div { echo "$1 / $2 'expr $1 - $2\11 'expr $1 / $2' (division entiere)" } function catcherr ( echo "On avait dit deux entiers ... :_) ,II echo "Au revoir." exit 1 trap catcherr ERR ### Saisir 2 valeurs ###clear echo IIBonjour," print "Veuillez saisir 2 valeur entieres (par ex. 3 5) \c" read un deux ### Verifier que ce sont deux entiers ### Proposer une operation PS3="Que voulez vous faire avec Sun et $deux (1-4, 5-quitter, ret-menu) ? Il select op in addition soustraction multiplication division quitter do case $REPLY in 1 ) add Sun $deux ;; 2 ) sub Sun $deux
echo "Impossible, merci de donner une valeur entre 1 et exit 1 3 ) mul Sun $deux 4 ) div Sun $deux 5 ) echo "Au revoir ... 11 exit 0 * ) esac dane ### exit 0
Et avec la fonction modulo ... } function sub { echo "$1 - $2 'expr $1 - $2\11 #! jbinjksh # # tpSbis.ksh # # Appel: .jtpSbis.ksh # # # # ############################# ### Initialisation des variables typeset -i un types et -i deux ### Fonctions du programme function add { echo "$1 + $2 ~ 'expr $1 + $2'" function rouI { echo "$1 * $2 } function div { Echo "$1 / $2 } function rnod { Echo n$1 % $2 Echo "$1 $2 'expr $1 \* $2 '" 'expr $1 / $2' (division entiere)" 'expr $1 % $2\11 'expr $1 / $2', reste 'expr $1 % $2 '" } function catcherr { Echo "On avait dit deux entiers ... :_) ,II Echo "Au revoir. 11 exit 1 trap catcherr ERR ### Saisir 2 valeurs ###clear Echo IIBonjour, Il print "Veuillez saisir 2 valeur entieres (par ex. 3 5) \cn read un deux ### Verifier que ce sont deux entiers ### Proposer une operation PS3="Que voulez vous faire avec Sun et $deux (1-5, 6-quitter, ret-menu) ? select op in addition soustraction multiplication division modula quitter do case $REPLY in 1 ) add Sun $deux , , 2 ) sub Sun $deux , , 3 ) mul Sun $deux ii 4 ) div Sun $deux , , 5 ) mod Sun $deux , , 6 ) Echo IIAu revoir ... 11 exit 0
echo IIImpossible, merci de donner une valeur entre 1 et exit 1 . ) esac done ### exit 0
TP6 Exemple de traitement des interruptions, utilisation des fonctions et de la boucle while Ecrire un script tp6. ksh qui réalise dans une boucle infinie while la création puis le grossissement d'un fichier par la redirection d'un message dans le fichier. Le script intercepte les signaux INT, QUIT et TERM comme suit Ignore le signal QUIT ( 3 ) Sur réception du signal INT ( 2 ) ou TERM ( 15), appelle une fonction de déroutement qui supprime le fichier Appel: $ ./tp6.ksh touch $FICHIER #!/bin/ksh # # tp6.ksh # # Appel: ./tp6.ksh # # # # ############################# ### Initialisation des variables FICHIER=/tmp/fic$$ if [ -e $FICHIER 1 then else echo "Le fichier $FICHIER existe deja ... Je sors." exit 1 fi ### Fonctions du programme function catchINT { echo "Vous avez tape un kill -2 (INT) programme 11 } function catchQUIT echo "Vous avez tape un kill -3 (QUIT) programme" } function catchTERM echo "Vous avez tape un kill -15 (TERM) programme" ls -al $FICHIER cat $FICHIER echo "Suppression du fichier $FICHIER dans 5 sec. Il sleep 5 rm $FICHIER echo "Au revoir. Il exit 0 echo go ### Interceptions trap catchINT INT trap catchQUIT QUIT trap catchTERM TERM ### Tester l'existence du fichier de depart et le creer si necessaire ### Fonctions du programme while true
date » $FICHIER sleep 5 do done exit 0
B.2 CORRIGES D'EXERCICES SUR LES FILTRES Dans la suite la référence au fichier" exemple" est faite à partir du contenu vu ci-dessous rager rene marie Marcel paul rager Rene marie marie Sophie Sylvie Paul michel Mireille Paul Rene Paul Andre martin 12000 cd1 duval 500 cd1 pervenche 12010 cd3 dupond 600 cd2 martin 10000 cd4 martin 12500 cd1 DUVAL 510 cd1 pervenche 13000 cd3 martin 13000 cd3 Martinez 6512 cd2 Martinelli 45678 cd2 Legrand 4560 cd5 DUVAL 54500 cd1 Duvalier 12345 cd2 LEGRAND 14560 cd5 Pervenche 5400 cd3 martinez 5600 cd2 dupond 650 cd5 Exercice 1 Utilitaire de tri sort sur le fichier exemple 1) Trier sur le troisième champ en ordre décroissant Marcel Rene rene $ dupond DUVAL duval 600 cd2 510 cd1 500 cdl $ sort -k3nr exemple michel DUVAL 54500 cd1 Sylvie Martinelli 45678 cd2 Paul LEGRAND 14560 cd5 marie rnartin 13000 cd3 2) Trier sur le deuxième champ ( minuscules et majuscules confondues) $ sort -bf -k2 exemple Marcel dupond 600 cd2 Andre dupond 650 cd5 rene duval 500 cd1 Rene DUVAL 510 cd1 marie pervenche 12010 cd3 marie pervenche 13000 cd3 $ 3) Trier sur le deuxième champ ( minuscules et majuscules confondues ), puis deuxième passage sur le premier champ ( même critère), puis troisième passage sur le troisième champ marie Rene $ pervenche Pervenche 13000 cd3 5400 cd3 $ sort -bf -k2,2 -k1,1 -k3n,3n exemple Andre dupond 650 cd5
4) Trier sur les trois premiers caractères du deuxième champ ( critère code ascii ) $ sort Rene michel Mireille Paul -k2b,2.3b exemple DUVAL 510 DUVAL 54500 Duvalier 12345 LEGRAND 14560 cd1 cd1 cd2 cd5 rager marie marie $ martin pervenche pervenche 12500 cd1 12010 cd3 13000 cd3
Exercice 2 Utilitaire de tri sort sur des commandes ou fichiers du système 1) Trier le résultat de "ls -al" d'après la taille des fichiers $ ls -al 1 sort -n -k5 total 49 -rw-r--r-- 1 stage13 stage 25 Feb 8 17:25 .exrc -rw-r--r-- 1 stage13 stage 264 Feb 8 17:25 .kshrc -rwxr--r-- 1 stage13 stage 350 Feb 8 17:25 .xsession -rwxr----- 1 stage13 stage 367 Feb 8 17:25 .profile drwxr-xr-x 2 stage13 stage 512 Feb 25 12:28 -rwxr- -r-- 1 stage13 stage 943 Feb 20 15:56 deuxierne drwxr-xr-x 33 raot system 1024 Feb 24 23:20 -rw-r----- 1 stage13 stage 1206 Feb 25 13: 59 exemple $ 2) Trier le fichier letc/passwd d'après le numéro de login ( UID ) en ordre décroissant $ sort -t: -nr k3 /etc/passwd stage2:! :1002:1000:Compte_Formation:/home/stage2:/usr/bin/ksh stage1:! :1001:1000:Compte_Formation:/home/stagel:/usr/bin/ksh guest:! :100:100: :/home/guest: lpd:! :9:4294967294: :/: uucp:! :5:5: :/usr/lib/uucp: adm:! :4:4: :/var/adm: sys:! :3:3: :/usr/sys: $
2) Remplacer, dans le résultat de "Is -al", tout caractère n'étant ni un chiffre, ni un espace, ni un saut de ligne par la lettre X $ ls -al 1 tr -c "[0-9] \012" " [X.] " XXXXX 14 XXXXXXXXXX 2 XXXXX13 XXXXX 512 XXX 25 12X28 X XXXXXXXXXX 33 XXXX XXXXXX 1024 XXX 24 23X20 XX XXXXXXXXXX 1 XXXXX13 XXXXX 0 XXX 9 08X38 XXXXXXXXXXX XXXXXXXXXX 1 XXXXX13 XXXXX 196 XXX 8 17X25 XXXXXX XXXXXXXXXX 1 XXXXX13 XXXXX 25 XXX 8 17X25 XXXXX XXXXXXXXXX 1 XXXXX13 XXXXX 264 XXX 8 17X25 XXXXXX XXXXXXXXXX 1 XXXXX13 XXXXX 241 XXX 8 17X25 XXXXXX
Exercice 4 Recherche d'expressions avec grep sur le fichier exemple 1) Rechercher les lignes du fichier" exemple" qui commencent par m ou M. $ grep " [mM] , exemple marie pervenche 12010 cd3 Marcel dupond 600 cd2 marie pervenche 13000 cd3 marie martin 13000 cd3 michel DUVAL 54500 cd1 Mireille Duvalier 12345 cd2 $ 2) Rechercher les lignes du fichier" exemple" qui comportent la lettre a en deuxième position. $ grep , ' .a' exemple marie pervenche 12010 cd3 Marcel dupond 600 cd2 paul martin 10000 cd4 marie pervenche 13000 cd3 marie martin 13000 cd3 Paul Legrand 4560 cd5 Paul LEGRAND 14560 cd5 Paul martinez 5600 cd2 $ 3) Rechercher les lignes du fichier" exemple" qui se terminent par l ou 2. $ grep , [12] $' exemple rager martin 12000 cd1 rene duval 500 cd1 Marcel dupond 600 cd2 rager martin 12500 cd1 Rene DUVAL 510 cd1 Sophie f\'lartinez 6512 cd2 Sylvie Martinelli 45678 cd2 michel DUVAL 54500 cdl Mireille Duvalier 12345 cd2 Paul martinez 5600 cd2 $ 4) Rechercher les lignes du fichier" exemple" qui commencent par une majuscule OU qui se terminent par la chaîne" cdl" . DUVAL Martinez Martinelli Legrand DUVAL Duvalier LEGRAND Pervenche rnartinez dupond 12000 500 600 12500 510 6512 45678 4560 54500 12345 14560 5400 5600 650 cd1 cd1 cd2 cd1 cd1 cd2 cd2 cd5 cd1 cd2 cd5 cd3 cd2 cd5 $ egrep rager rene Marcel rager Rene Sophie Sylvie Paul michel Mireille Paul Rene Paul Andre $ " [A-Z] 1 cd1$' exemple martin duval dupond martin
5) Rechercher les lignes du fichier" exemple" qui commencent par une majuscule ET qui se terminent par la chaîne" cd2" ( avec le résultat trié sur le troisième champ en ordre décroissant ). $ grep "[A-Z] . cd2$' exemple Sylvie Martinelli Mireille Duvalier Sophie Martinez Paul martinez Marcel dupond $ 1 sort -nr -k3,3 45678 12345 6512 5600 600 cd2 cd2 cd2 cd2 cd2
Exercice 5 Recherche d'expressions avec grep sur le fichier / etc/passwd 1) Dans le fichier /etc/passwd, rechercher les lignes correspondant aux utilisateurs du Korn-shell. $ $ grep 'bin/ksh *$' /etc/passwd root:! :0:0: :/:/bin/ksh netinst:*:200:1: :/home/netinst:/usr/binlksh stagel:! :lOOl:lOOO:Compte Formation:/home/stagel:!usr!bin/ksh stage2:! :1002:1000:compte=Formation:/home/stage2:!usr!bin!ksh stage3:! :1003:1000:Compte_Formation:!home!stage3:!usr/bin/ksh 2) Même question pour les utilisateurs potentiels du Bourne-shell. $ grep -e 'bin/sh' *$ -e ': *$' /etc/passwd ou encore $ egrep 'bin/sh *$ 1: *$' /etc/passwd ( quand le dernier champ est vide, le shell par défaut est le "Bourne"
sed sur Exercice 6 Edition non interactive de fichiers le fichier exemple 1) Dans les lignes du fichier" exemple" qui ne contiennent pas la chaîne » cdl" , remplacer la chaîne" cd" par la chaîne" code" . '/cd1/1s/cd/code/' exemple martin duval pervenche dupond rnartin martin DUVAL pervenche martin Martinez Martinelli Legrand $ sed rager rene marie Marcel paul roger Rene marie marie Sophie Sylvie Paul 12000 500 12010 600 10000 12500 510 13000 13000 6512 45678 4560 $ cdl cdl code3 code2 code4 cdl cd1 code3 code3 code2 code2 code5 2) Afficher le fichier" exemple" jusqu'à trouver la chaîne" cdS" ( ligne non comprise) . $ sed '/cd5/q' exemple 1 sed '$d' roger rnartin 12000 cd1 rene duval 500 cdl marie pervenche 12010 cd3 Marcel dupond 600 cd2 paul martin 10000 cd4 rager martin 12500 cdl Rene DUVAL 510 cd1 marie pervenche 13000 cd3 marie martin 13000 cd3 Sophie Martinez 6512 cd2 Sylvie Martinelli 45678 cd2 $ 3) Décaler, de quelques espaces, le début des lignes du fichier" exemple" commençant par une majuscule $ sed '/-[A-Zj/s/-/ /' exemple rager martin rene duval marie pervenche Marcel dupond paul martin rager martin Rene DUVAL marie pervenche marie martin Sophie Martinez Sylvie Martinelli Paul Legrand michel DUVAL Mireille Duvalier 12000 500 12010 600 10000 12500 510 13000 13000 6512 45678 4560 54500 12345 $ cd1 cdl cd3 cd2 cd4 cdl cd1 cd3 cd3 cd2 cd2 cd5 cd1 cd2 4) Mettre des parenthèses autour des lignes du fichier" exemple" qui se terminent par" cdl"
$ sed '/cd1$/s/ . /(&)/' exemple (roger martin 12000 cdl) (rene duval 500 cd L) marie pervenche 12010 cd3 Marcel dupond 600 cd2 paul martin 10000 cd4 (roger martin 12500 cd l ) (Rene DUVAL 510 cd l ) marie pervenche 13000 cd3 marie martin 13000 cd3 Sophie Martinez 6512 cd2 Sylvie Martinelli 45678 cd2 Paul Legrand 4560 cd5 (michel DUVAL 54500 cdl) $ 5) Idem" question 4" mais en n'affichant que les lignes modifiées, triées sur le deuxième champ ( minuscules et majuscules confondues) avec une deuxième passe sur le troisième champ en ordre décroissant $ sed '/cdl$/s/ . /(&)/' exemple (michel DUVAL (Rene DUVAL (rene duval (rager martin (rager martin $ 1 grep "(' 1 sort k2bf,2 54500 510 500 12500 12000 k3nr,3 cdl) cd l ) cd l.) cdl) cdl) 6) Remplacer tous les" 0" du fichier exemple par des" x" et tous les" 1" par des "y" $ cat commande s/o/x/g s/I/Y/g $ $ sed -f commande exemple rager martin Y2XXX cdY rene duval 5XX cdY marie pervenche Y2XYX cd3 Marcel dupond 6XX cd2 paul martin YXXXX cd4 rager martin Y25XX cdY Rene DUVAL 5YX cdY marie pervenche Y3XXX cd3 marie martin Y3XXX cd3 Sophie Martinez 65Y2 cd2 Sylvie Martinelli 45678 cd2 Paul Legrand 456X cdS michel DUVAL 545XX cdY Mireille Duvalier Y2345 cd2 Paul LEGRAND Y456X cdS Rene Pervenche 54XX cd3 Paul martinez 56XX cd2 Andre dupond 65X cdS $
Exercice 7 Traîternent sur le fichier exemple avec l'outil awk 1) Afficher le fichier en numérotant les lignes et en permutant les deux premières colonnes. $ awk '{ print NR , $2 , $1 , $3 ,$4 }' exemple $ awk '{print NR, $2, $1, $3, $4}' exemple 1 martin roger 12000 cd1 2 duval rene 500 cd1 3 pervenche marie 12010 cd3 4 dupond Marcel 600 cd2 5 martin paul 10000 cd4 6 martin roger 12500 cdl 7 DUVAL Rene 510 cdl 8 pervenche marie 13000 cd3 9 martin marie 13000 cd3 10 Martinez Sophie 6512 cd2 Il Martinelli Sylvie 45678 cd2 12 Legrand Paul 4560 cd5 13 DUVAL michel 54500 cd1 14 Duvalier Mireille 12345 cd2 15 LEGRAND Paul 14560 cd5 16 Pervenche Rene 5400 cd3 17 martinez Paul 5600 cd2 18 dupond Andre 650 cd5 $ 2) Afficher noms et prénoms des personnes correspondant aux codes "cd1" ou "cd2". $ awk $4 "cdl" Il $4 "cd2" END { printf "Total ~ %d\n" r n exemple martin roger cdl duval rene cdl dupond Marcel cd2 martin roger cd1 DUVAL Rene cd1 Martinez Sophie cd2 Martinelli Sylvie cd2 DUVAL michel cd1 Duvalier Mireille cd2 martinez Paul cd2 Total ~ 10 $ $2 , $1 , $4 n++ } { print } 3) Afficher la ligne pour laquelle le nombre ( 3ème colonne) est le plus grand. $ awk $3 > max END exemple michel $ max ~ $3 print ligne ligne } $0 DUVAL 54500 cd1 4) Pour chaque code, afficher le total des nombres ( 3ème colonne ). Afficher en final la moyenne des nombres.
} exemple cd1 80010 cd2 70735 cd3 43410 cd4 10000 cdS 19770 Moyenne des nombres $ 12440,277778 $ awk ' { END ( tab[$41 +~ $3 total +~ $3 for ( code in tab) print code, tab[codeJ printf "Moyenne des nombres ~ %f\n" , total / NR
B.3 CORRIGES D'EXERCICES DE L'ATELIER DE PROGRAMMATION SHELL Atelier 1 Modification de nom de fichiers avec confirmation éventuelle et gestion de la ligne de commandes Ecrire un script atelierl.kshqui recoit deux arguments .extl et .ext2. Le but du script est de renommer tous les fichiers d'extension. extl du répertoire courant en *. ext2. Le script vérifiera que les arguments sont des" extensions:" "suivi de l'extension en minuscules. Si on donne l'option" - i " , le script propose la confirmation pour chaque fichier. Note: Penser à utiliser la commande basename sur les noms de fichiers à traiter Syntaxe: $ basename string [suffix] Appel: $ atelierl. ksh [ -i .extl .ext2 mauvais_appel #!/bin/ksh # atelier1 function mauvais_appel echo "Usage: $0 [-il .ext1 .ext2\n" exit 1 function mauvais arg { - if [[ $1 != @(.+([a-z]» Il $2 != @(.+([a-z])]] then return 0 else return 1 fi conf=O if test $# -gt 3 -0 $# -lt 2 then mauvais_appel fi if test $# -eq 3 ; then if test $1 = -i then conf=1 shift el se fi fi if mauvais_arg $1 $2 then
integer nombre=O for f in *$1 do # si aucun fichier d'extension $1 n'existe, on sort if test $f "*$11'; then Echo uII n'y a pas de fichiers d'extension $111 exit 2 mauvais_appel fi fi if test $eonf = 1 ; then read rep? Il Renommer $f (a/n) . 11 if test -il II$rep'l ; then if test $rep = 0 ; then newname=$(basename $f $1)$2 rnv $f $newname nombre::::nombre+l fi fi else newname=$(basename $f $1)$2 rnv $f $newname nombre=nombre+l fi done Echo IINombre de fichiers renommes $nombre"
Atelier 2 Autre script de modification de nom de fichiers Ecrire un script atelier2 .ksh qui recoit des noms de fichiers en arguments. Pour chaque argument, s'il s'agit d'un fichier ordinaire dont le nom ne contient que des MAJUSCULES, on le renomme en minuscules. Appcl: $ atelier2.ksh liste_fichiers #l/usr/bin/ksh # atelier2 typeset -i nombre=O for f in $* do if [[ $f = + ([A-Z]) ]] then if test -f $f then newname=$(echo $f 1 tr 00 [A-Z] 00 00 [a-z] 00) echo "On renomme $f en $newnarne" mv $f $newname nombre=nombre+l fi fi done echo "Nombre de fichiers renommes $nombre"
Atelier 3 Traitements sur les fichiers : test Ecrire un script atelier3 . ksh qui recoit des noms de fichiers en arguments. Si le fichier existe et est un fichier ordinaire, on affiche sa taille. Si le fichier n'existe pas, on le créée de taille O. Si l'option" -c" est utilisée, le script ne créée pas le fichier s'il n'existe pas. Appel: $ atelier3.ksh [ -c ] liste_fichiers fi #! /usr/bin/ksh # atelier3 if test $# -ne 0 then if test $1 -c then option=o shift if test $# -eq 0 ; then Echo 11Usage : $0 [-el liste de fichiers Il exit 1 fi else option=n fi for f in $* do if test -e $f then if test -f $f ; then t.ad LLe » 'wc -c $f 1 awk "{p r Lnt. s i }: , Echo l'Taille de Sf = $taille octet(s) Il fi el se if test $option = 0 then Echo IIOption -c demandee je ne cree pas $fll else > $f Echo rrCreation de $f ( taille 0 ) Il fi done fi
Atelier4 Menu simple avec case et appel de commandes UNIX Ecrire un script atelier4. ksh sous la forme d'un menu dans une boucle until. Le script prévoit avec la structure case : 1. L'affichage de l'heure 2. Le changement de répertoire courant 3. La sauvegarde au format tar compressé des fichiers ordinaires du répertoire courant après avoir vérifié qu'il y en a Après saisie du nom de l'archive souhaité, la création de celle-ci se fait sous jtmp 4. La liste du contenu d'une archive dont on saisit le nom 5. La Restauration interactive de fichiers d'une archive 6. a La Sortie Rappel sur la syntaxe de tar : Création d'une archive: tar -cvf fichier_archive lis te_a_sauvegarder Lecture d'une archive: tar -tvf fichier_archive Imore Restauration d'une archive tar -xvf fichier_archive liste_a_restaurer Appel: $ atelier4.ksh #! /bin/ksh # atelier4 fin=O ; clear fictemp=/tmp/liste$$ until test "$rep" = $fin do cat «'FIN MENU' O. SORTIE 1. QUELLE HEURE EST-IL? 2. CHANGEMENT DE REPERTOIRE COURANT 3. SAUVEGARDE ( ARCHIVE TAR COMPRESSEE 4. LISTE D'UNE ARCHIVE 5. RESTAURATION INTERACTIVE FIN MENU read rep?"Votre choix case "$rep" in $fin) echo "Au revoir et Mercin exit 0 1) echo "\nll est 'date '+%H h %M' '\nl! 2) echo "Nouveau repertoire ( ou Return ou home) \clI read fie if [ -n l1$ficlI ] then
if [$fic home 1 then cd elif [ -d $fic -a -x $fic J then cd $fic el se Echo n\n?? Changement de repertoire impossible. Il fi fi Echo lI\nRepertoire courant $PWD\n" 3) > $fictemp n=O for i in .7?* * do if test -f $i ; then Echo $i » $fictemp let TI=n+1 fi done if test $n -gt 0 then echo "Il y a $n fichiers dans $PWD" read archive?"Norn de l'archive ( Return pour abandonner) . 11 if test -il l'$archive'' then tar cvf - 'cat $fictemp' 1 compress > /tmp/${archive}.tar.Z Echo IISauvegarde $archive effectueell fi rm -f $fictemp else Echo 1'11 n'y a pas de fichiers ordinaires dans $PWD'1 fi ii 4) read archive? Il Nom de l'archive ( Return pour abandonner) if test -n l'$archive'l then fic=/tmp/${archive}.tar.Z if test -f $fic ; then uncompress < $fic 1 tar tvf - el se Echo ,'?? L'archive SEie n'existe pas" fi fi i : 5) read archive?IINom de l'archive ( Return pour abandonner) if test -il Il $archive Il then fic=/tmp/${archive}.tar.Z if test -f $fic ; then Echo "Fichier a restaurer \clI read nom if test -TI lI$nom" i then uncompress < $fic 1 tar xvf - $nom fi else Echo "?? L'archive $fic n'existe pas" fi fi ii *) echo 1177 Choix irnpossible\nl1 ii esac if test l'$rep'l != $fin then
echo "TAPEZ RETURN POUR CONTINUER \c" ; read bidon clear fi done
Atelier 5 Gestion de la ligne de commande et traitement sur les fichiers Ecrire un script atelierS. ksh qui reçoit en premier argument un entier puis une liste de fichiers. Le script vérifie que le premier argument est un entier. Il affiche pour chaque fichier les lignes plus longues que cette valeur et le nombre de lignes. App~: $ atelierS.ksh valeur liste_fichiers #! /bin/ksh # atelierS if test $# -lt 2 then Echo "Usage $0 longueur liste de fichiersll exit l fi if [[ $1 +([0-9])]] then longueur~$l else Echo 11Usage $0 longueur liste de fichiers" exit 1 fi selection=111ength > $ln shift for f in $_ do Echo f!Fichier $f : Lignes plus longues que $longueur caracteres" awk Il $selection {print; n++ } END { if ( n > 0 ) printf \"Nombre de lignes $f %s\n\" , n } done
Atelier 6 Traitements sur les fichiers et Expressions arithmétiques Ecrire un script atelier6 .ksh qui reçoit une liste de noms de fichiers en arguments. Le script ne conserve de la liste d'arguments que les fichiers ordinaires et affiche la taille en octets de chacun, la taille totale ainsi que le nom du plus gros fichier. Appel: $ atelier6.ksh liste_fichiers taille += $5 if ( $5 > max ) { fic=$9 ; tfic=$5 max=$5} n++ printf "%16d\t%s\n", $5, $9 #! /hin/ksh # atelier6 integer i=O for arg in $_ do if test -f $arg ; then liste [il =$arg i~i+l fi done if (( i = = 0 » ; then echo IILa liste d'arguments ne contient pas de fichiers ordinaires!!U exit 1 fi ls -1 ${liste [-l} awk ' BEGIN NF > 2 printf "%s\t%s\n","TAILLE EN OCTETS","FICHIERS" 1 max=O } END printf "TAILLE TOTALE : %d ( %d fichiers) \n", taille, n printf "LE PLUS GROS: %s ( %d octets )\n",fic,tfic
Atelier 7 Habillage de la commande find et utilisation de fonctions Le script atelier7 . ksh propose par menu d'utiliser la commande find. Les critères suivants sont proposés : nom Le script appelle l'option -name de find. proprietaire Le script appelle l'option -user de find. Le script vérifie qu'on donne un "login" existant dates Le script propose dans un sous-menu l'une des options de find suivantes: -mtime , -atime ou -newer Pour chaque critère, le script fait la saisie au clavier de l'argument correspondant à l'option choisie. Le script affiche la commande correspondant aux choix de l'utilisateur. Celle-ci est lancée après confirmation de l'utilisateur Le script permet d'interrompre l'exécution de la commande find sans quitter le programme complet. Appcl: $ atelier7.ksh function lit_reponse { # Premier argument # Deuxieme argument print 1'\n$1 : \CII read $2 la question la variable receptionnant la reponse Il! /bin/ksh Il atelier7 function ok commande Il Affiche la commande a lancer. # Retourne 0 si ok pour la lancer et 1 sinon print OK pour: find $1 $2 $3 -print (o/n) \c typeset -1 reponse read reponse if [ "$reponsett = 0 then return 0 else return 1 fi function veriE login { - # Retourne 0 si l'argument est un login sur le systeme grep '$1: /etc/passwd >/dev/null 2>&1 return $? PS3="Votre critere
$ (Liste [2] }) print \\n\\n select j in "Modifies aujourd'huill IIPlus jeune quell liNon accedes depuisll "FinI! do case $REPLY in 1) Annexe B set -A Liste Nom Proprietaire Dates Sortie while test lI$ill (= Sortie do clear select i in ${Liste[*]} do case $i in $(Liste [0] }) critere=-name lit reponse IINom cherchell arg $ (Liste [1] }) critere=-user lit_reponse "Nom du login" arg verif 1091D "$arg" if test $? != 0 then print 1I?? $arg n'est pas un nom de login" print IIReturn pour continuer. \en ; read break fi " critere=-mtime arg=-l break 2) critere=-newer lit reponse "Nom du fichier!! arg break ;; 3) critere=-atime lit_reponse lINombre de jours" arg arg=+"$arg" break 4) break 2 ;; esac done Sortie) print IIAu revoir et merci\n\n" ; break, 1 1111) print "Choix impossible\n\n" i break, f esac lit_reponse "Repertoire" dir if ok_commande lI$dir" n$criteren "$arg" then trap 'break' 2 3 # pouvoir abandonner find par un break clavier find n$dirll n$critere" n$arg" -print 1 more print "Return pour continuer. \c" ; read fi break done trap 2 3 # fin du select # reprise du comportement par defaut done # fin du while
Atelier 8 Traitement de la ligne de commande Ecrire un script atelierS. ksh qui traite La Ligne de commande de La façon suivante: Si on a saisi" -u user" Le script affiche le nom des groupes de "user" après vérification qu'il s'agit d'un "user" existant. Sans l'option, il affiche ses propres groupes . " - t" Le script affiche le type de terminal de connexion. S'il y a des arguments, le script les affiche tels quels. Note: Il est possible d'utiliser getopts Appel: $ atelier8.ksh [ -u user [ - t ] #! /bin/ksh # atelier8 # exemple de corrig\'e avec utilisation de getopts user~$LOGNAME while getapts ,u,t apt do case Sapt in u) user~$OPTARG # L'argument de -u ne doit pas commencer par un - if [[ $OPTARG 11 then print -u2 "Ue a qe : $0 [ -u user] [ -t ] parametres ... fi exit l fi aptianu~VRAI; ; t) optiont~VRAI;; :) print -u2 11$0 : L'option -$OPTARG requiert un argumentll print -u2 "Usage: $0 [ -u user] [ -t ] parametres exit 1 ;i ?) print -u2 "$0 : -$OPTARG : Option 111ega1ell print -u2 "Usage: $0 [ -u user 1 [ -t 1 parametres exitl;; esac done shift QPTIND-l if [[ "sopt.Lonu'' liVRAI Il ]] then grep 11~$user:l1 /etc/passwd > /dev/null 2>&1 if [[ $? -ne 0 11 then print -u2 lI$user n'est pas un utilisateur de 'uname _n'II else eeho "Les groupes de $userll groups $user fi el se echo liMes groupes: $ (groups) Il fi if [[ Il $optiont Il = liVRAI Il ]] then print IIType du terminal: $TERMII fi if [ $# -ne 0 1 then
1 _ echo "Arguments ~ -------------------------------------------------------------- $*"
Index awk,67,77 tee, 62 test, 25 tr, 66 typeset,46,54 break, 31 case, 35 continue, 31 eut, 62 unset,8 until,30 eval,48 ex, 67 exec,39 export,18 expr,33 whence,48 while,30 Fonctions, 50 getopts,71 Graticiels, 59 grep,67,69 head,61 if, 22 IFS, 42 integer,34 let, 34 nawk,67 printf,47 print,47 read,32 return,53 sed, 67, 74 select, 36 set, 43 shebang,18 shift,42 Signaux, 45 sort, 64 tail,62