Chapitre 14 : Les particularités du Korn Shell
Si le Bourne Shell est un shell POSIX présent et standard sur tous les UNIX, le Korn Shell, apparu dans sa version moderne sous System V release 4 devient aujourd’hui un standard de fait. Le Korn Shell ou ksh est entièrement compatible avec le Bourne Shell (scripts exécutables sans modification) et le Bourne Again Shell (bash sous Linux). Ksh est présent sous Linux avec le nom pdksh.
Parmi les nouvelles possibilités :
- Les alias
- Possibilité de typer les variables, gestion des tableaux et des chaînes
- commandes supplémentaires
- gestion des jobs
Le fichier de configuration par défaut est le fichier .profile. On peut y placer ses définitions de variables, alias, …
Historique et répétition
On peut accéder à l’historique des commandes avec la commande fc. Cette commande permet aussi de rappeler une ligne précise ou d’en modifier le contenu. La taille de l’historique se contrôle avec la valeur de la variable HISTSIZE (HISTSIZE=200 prendra en compte les 200 dernières commandes).
$ fc -l
201 ls -ltr
202 pg transpo19659.lst
203 ls -ltr
204 pg syn19659.lst
205 exit
206 fc -l
207 man fc
208 fc -l
$ fc -s 201
ls -ltr
total 30
lrwxrwxrwx 1 oracle system 4 Aug 14 15:21 lien_fic1 -> fic1
lrwxrwxrwx 1 oracle system 4 Aug 14 15:21 lien_fic2 -> fic2
-rw-r--r-- 1 oracle system 1392 Aug 14 15:55 dump.log
-rw-r--r-- 1 oracle system 1496 Aug 14 16:12 resultat.txt
-rwxr--r-- 1 oracle system 12 Aug 16 12:07 voir_a.sh
-rw-r--r-- 1 oracle system 234 Aug 16 12:20 liste1
-rw-r--r-- 1 oracle system 1715 Aug 16 14:55 toto.txt
-rwxr--r-- 1 oracle system 288 Aug 19 09:05 param.sh
-rwxr--r-- 1 oracle system 430 Aug 19 09:09 param2.sh
-rwxr--r-- 1 oracle system 292 Aug 19 10:57 param3.sh
drwxr-xr-x 2 oracle system 8192 Aug 19 12:09 rep1
-rwxr--r-- 1 oracle system 265 Aug 19 12:38 param4.sh
-rwxr--r-- 1 oracle system 327 Aug 19 13:31 case1.sh
-rwxr--r-- 1 oracle system 338 Aug 19 13:51 read.sh
Modes vi et emacs
Par défaut les touches de la ligne de commande émettent régulièrement des caractères bizarres, ou rien du tout, et ne sont pas interprétées par le shell. C’est souvent le cas des touches de direction, ou backspace.
$ toucd^[[D^[[D^[[D^[[A^[[B^[[C
La commande
$ set -o vi
commute la ligne de commande en mode vi , permettant l’utilisation des touches de types vi pour la saisie et le rappel de commandes avec l’utilisation de la touche Echap.
| Touche | Action |
|---|---|
| k | Vers le haut, rappel d’une ligne précédente de l’historique |
| j | Vers le bas, ligne suivante de l’historique |
| h | Vers la gauche, curseur vers la gauche |
| l | Vers la droite, curseur vers la droite |
| w | Curseur sur le mot suivant |
| b | Curseur sur le mot précédent |
| $ | Vers la fin de ligne |
| 0 (zéro) | Vers le début de ligne |
| x | Suppression d’un caractère |
| i | Insertion devant le caractère courant |
| a | Insertion derrière le caractère actif |
$ set -o emacs
passe la ligne de commande en mode emacs. Un avantage certain dans ce cas est que les touches directionnelles peuvent être utilisées pour déplacer le curseur et afficher l’historique.
Le contenu de la variable VISUAL peut être modifié en conséquence avec la valeur vi ou emacs.
Les alias
La commande alias ajoute un alias, une substitution d’une commande par un raccourci. L’alias est prioritaire sur les fonctions, commandes internes et commandes externes. Il est possible d’y substituer du texte.
alias nom_alias=commande_ou_texte
Exemple :
$ alias deltree='rm -rf'
$ deltree rep1
La substitution ne s’effectue que si l’alias est la première commande ou si le texte de l’alias se termine par un espace.
$ alias list='ls -l '
$ alias home='/tmp/seb'
$ list home
total 22
-rwxr--r-- 1 oracle system 327 Aug 19 13:31 case1.sh
-rw-r--r-- 1 oracle system 1392 Aug 14 15:55 dump.log
-rwxr--r-- 1 oracle system 200 Aug 19 15:58 expr1.sh
-rw-r--r-- 1 oracle system 42 Aug 19 15:43 fonction
-rwxr--r-- 1 oracle system 57 Aug 19 14:06 for1.sh
-rwxr--r-- 1 oracle system 66 Aug 19 14:09 for2.sh
-rwxr--r-- 1 oracle system 285 Aug 19 14:32 for3.sh
-rwxr--r-- 1 oracle system 133 Aug 19 14:37 for4.sh
lrwxrwxrwx 1 oracle system 4 Aug 14 15:21 lien_fic1 -> fic1
lrwxrwxrwx 1 oracle system 4 Aug 14 15:21 lien_fic2 -> fic2
...
Sans paramètre, c’est la liste des alias qui s’affiche.
$ alias
autoload='typeset -fu'
cat=/usr/bin/cat
command='command '
deltree='rm -rf'
functions='typeset -f'
grep=/usr/bin/grep
hash='alias -t -'
history='fc -l'
home=/tmp/seb
integer='typeset -i'
list='ls -l '
local=typeset
ls=/usr/bin/ls
nohup='nohup '
r='fc -e -'
rm=/usr/bin/rm
stop='kill -STOP'
suspend='kill -STOP $$'
type='whence -v'
L’option -x d’exporter l’alias. Enfin la commande unalias supprime l’alias.
Modifications concernant les variables
Variables système
Voici quelques nouvelles variables système.
| Variable | Contenu |
|---|---|
ENV |
Nom du fichier devant être exécuté à chaque chargement du Korn Shell, en plus de /etc/profile et $HOME/.profile. Généralement il s’agit de $HOME/.kshrc |
FPATH |
Chemin de recherche pour les fonctions inconnues. Si une fonction n’est pas connue, le shell recherche un fichier dans ce chemin portant le nom de cette fonction et intègre son contenu. |
HISTFILE |
Nom du fichier historique, généralement $HOME/.sh\_history |
HISTSIZE |
Taille en nombre de lignes de l’historique |
OLDPWD |
Chemin d’accès du répertoire accédé précédemment. |
PS3 |
Définit l’invite de saisie pour un select |
PWD |
Chemin d’accès courant |
RANDOM |
Génère et contient un nombre aléatoire entre 0 et 32767 |
SECONDS |
Nombre de secondes depuis le lancement du shell |
TMOUT |
Délai d’attente maxi en secondes pour une saisie. A la fin de ce temps le shell se quitte |
VISUAL |
Mode d’édition en ligne, vi ou emacs. |
Longueur d’une chaîne
Il est maintenant possible d’obtenir la longueur d’une chaîne autrement qu’avec la commande expr. On utilise le caractère « # »
$ a=Jules
$ echo "Longueur de $a : ${#a}"
Longueur de Jules : 5
Tableaux et champs
Le ksh introduit la gestion des tableaux de variables Deux moyens sont disponibles pour déclarer un tableau, l’un avec l’utilisation des crochets « [] », l’autre avec la commande set -A. Le premier élément est 0 le dernier 1023. Pour accéder au contenu du tableau il faut mettre la variable ET l’élément entre accolades « {} ».
$ Nom[0]="Jules"
$ Nom[1]="Romain"
$ Nom[2]="Francois"
$ echo ${Nom[1]}
Romain
ou
$ set -A Nom Jules Romain Francois
$ echo ${nom[2]}
Francois
Pour lister tous les éléments :
$ echo ${Nom[\*]}
Jules Romain Francois
Pour connaître le nombre d’éléments
$ echo ${#Nom[\*]}
3
Si l’index est une variable, on ne met pas le $ :
$ idx=0
$ echo ${Nom[idx]}
Jules
Opérations sur chaînes
Les recherches sur chaînes sont maintenant possibles au sein même de la variable. Le texte trouvé en fonction de critères est supprimé de la variable.
${variable<Opérateur>Critère}
| Opérateur | Rôle |
|---|---|
# |
Cherche la plus petite survenance du critère en début de chaîne |
## |
Cherche la plus grande survenance du critère en début de chaîne |
% |
Cherche la plus petite survenance du critère en fin de chaîne |
%% |
Cherche la plus grande survenance du critère en fin de chaîne |
$ a="Bonjour les amis"
$ echo ${a#Bon*}
jour les amis
$ echo ${a##Bon*}
La commande typeset propose quelques options intéressantes
| Option | Rôle |
|---|---|
-l |
Les majuscules sont converties en majuscules et le contenu sera toujours automatiquement converti en minuscules |
-u |
Les minuscules sont converties en majuscules, même remarque |
-r |
La variable sera en Read Only |
-x |
La variable est exportée |
-Ln |
Justification à gauche avec suppression des espaces à droite et gauche. si n est positionné la chaîne est tronquée à n caractères ou augmentée avec des espaces à droite |
--Rn |
Idem mais pour la justification à droite |
-Z |
Si le premier caractère est un chiffre, justification et remplissage avec des 0 (zéro), n étant la taille du champ |
$ typeset -u txt1
$ txt1="abcdefg"
ABCDEFG
$ typeset -u txt1
$ echo $txt1
abcdefg
Variables typées
Les variables peuvent être typées en entier (integer) avec la commande typeset -i le permet. L’avantage est qu’il devient possible d’effectuer des calculs et des comparaisons sans passer par expr. La commande let ou « ((…)) » permet des calcules sur variables.
| Opérateur | Rôle |
|---|---|
+ - \* / |
Opérations simples |
% |
Modulo |
< > \<= >= |
Comparaisons. 1 si vraie, 0 si faux |
== != |
Egal ou différent |
&& || |
Comparaisons liées par un opérateur logique |
& | ^ |
logique binaire AND OR XOR |
$ typeset -i resultat
$ resultat=6*7
$ echo $resultat
42
$ resultat=Erreur
ksh: Erreur: bad number
$ resultat=resultat*3
126
$ typeset -i add
$ add=5
$ let resultat=add+5 resultat=resultat*add
$ echo $resultat
50
Nouvelle substitution de commande
On peut toujours utiliser les accents pour effectuer une substitution de commandes, mais il est maintenant plus simple d’utiliser la syntaxe « $(…) ».
$ date_courante=$(date)
$ echo $date_courante
Tue Aug 20 16:07:05 MET DST 2002
cd
Nous avons vu deux nouvelles variables nouvelles PWD et OLDPWD. La nouvelle commande cd permet de les exploiter. cd -, on retourne dans le catalogue précédent.
$ pwd
/tmp/seb
$ cd ..
$ pwd
/tmp
$ cd -
$ pwd
/tmp/seb
Le tilde permet un raccourci pour le répertoire utilisateur.
$ cd ~rep1
$ pwd
/tmp/seb/rep1
Enfin,
$ cd rep1 rep2
$ pwd
/tmp/seb/rep2
Gestion de jobs
Lorsqu’un processus est lancé en tâche de fond, ksh affiche en plus du PID un numéro entre crochets. Il s’agit d’un numéro de job, incrémenté de 1 à chaque nouveau lancement si les commandes précédentes ne sont pas terminées. La commande jobs permet d’obtenir des informations.
$ ls -lR > /toto.txt &
[1] 25994
$ jobs -l
[1] + Running ls -lR / >toto.txt 2>&1 &
Le processus de PID 25994 a été lancé avec le numéro de job 1. Son état actuel est running (il peut être Done , Stopped , Terminated ).
Pour interrompre un processus en premier plan sans le quitter (le passer en stopped mais pas en terminated) on utilise généralement la séquence Ctrl+Z. Dans ce cas le processus est stoppé mais pas terminé, et on a accès à la ligne de commande. Pour le relancer en arrière-plan on utilise la commande bg %n (background, n numéro de job). Pour replacer une commande en arrière-plan au premier plan, on utilise la commande fg %n (foreground, n numéro de job).
$ ls -lR / >toto.txt 2>&1
[1] + Stopped ls -lR / >toto.txt 2>&1
$ bg %1
[1] ls -lR / >toto.txt 2>&1&
$ jobs -l
[1] + 26329 Running ls -lR / >toto.txt 2>&1
$ fg %1
ls -lR / >toto.txt 2>&1
La commande kill dans sa nouvelle syntaxe peut effectuer la même chose.
kill -STOP %1 <-> Ctrl+Z
kill -CONT %1 <-> fg %1
La commande print est une extension de la commande echo, et accepte de nouveaux paramètres en plus de ceux de la commande echo.
| Option | Rôle |
|---|---|
- |
Les mots situés après sont des paramètres, pas des options |
-R |
Les caractères spéciaux ne sont plus interprétés |
-n |
N’effectue pas de saut de ligne |
-s |
Les paramètres sont consignés dans le fichier historique |
-nChiffre |
Les paramètres sont envoyés dans le canal n |
$ print "Bonjour, \n Comment ça va ?\c"
Bonjour,
Comment ça va ?$
$ print -R "Bonjour, \n Comment ça va ?\c"
Bonjour, \n Comment ça va ?\c
Tests étendus
Une nouvelle commande interne au ksh permet des tests étendus et généralement plus performants, par l’utilisation des doubles-crochets « [[…]] ». Il existe quelques différences entre la commande test (ou []) et la nouvelle.
- Les caractères spéciaux (métacaractères) de recherche de fichiers ne sont pas interprétés.
- -a et -o (ET et OU) sont remplacés pas « && » et « || ».
- Si deux chaînes sont comparées, la deuxième peut être un modèle (de type case).
- La recherche des opérateurs est effectuée avant la substitution des variables.
$ [[-d "rep1" && -r "rep1"]] && echo "rep1 ; repertoire avec droits write"
Voici les nouveaux modèles pour la comparaison de texte :
| Modèle | Rôle |
|---|---|
?(Critere1|Critere2...) |
Un seul des critères peut survenir |
*(Critere1|Critere2...) |
Chaque critère peut survenir plusieurs fois |
+(Critere1|Critere2...) |
Un des critères doit survenir au moins une fois |
@(Critere1|Critere2...) |
Au moins un critère doit survenir au moins une fois |
!(Critere1|Critere2...) |
Aucun des critères ne doit survenir |
Options du shell
La commande set permet d’autres options que vi et emacs. L’option -o active l’option, +o l’annule. La commande set -o sans rien d’autre affiche la liste des options et leur état.
- allexport : toutes les variables déclarées seront automatiquement exportées
- bgnice : les processus lancés en tâche de fond ont un facteur nice plus important et donc tournent avec une priorité moindre
- ignoreeof : La combinaison Ctrl+d n’est plus interprétée.
- noclobber : la redirection
>n’écrase plus le fichier et produit un message d’erreur s’il existe. Pour l’écraser tout de même :\>|
$ set -o noclobber
$ wc -l toto.txt
378264 toto.txt
$ ls > toto.txt
ksh: toto.txt: file already exists
$ ls >| toto.txt
$ wc -l toto.txt
18 toto.txt
$ set +o noclobber
Commande whence
La commande whence indique le type de commande lancée
$ whence -v cd
cd is a shell builtin
$ whence -v test
test is a shell builtin
$ whence -v ls
ls is a tracked alias for /usr/bin/ls
$ whence -v rm
rm is a tracked alias for /usr/bin/rm
$ whence -v echo
echo is a shell builtin
$ whence -v touch
touch is /usr/bin/touch
| Valeur | Signification |
|---|---|
shell builtin |
Commande interne au shell |
Alias |
Alias de commande |
tracked alias |
Alias avec suite |
keyword |
Mot-clé |
exported alias |
alias exporté |
function |
Une fonction du shell |
undefined function |
fonction non définie |
program <nom du programme> |
un programme externe |
Commande select
La commande select permet de créer des menus simples, avec sélection par numéro. La saisie s’effectue au clavier avec le prompt de la variable PS3. Si la valeur saisie est incorrecte, une boucle s’effectue et le menu s’affiche à nouveau. Pour sortir d’un select il faut utiliser un break.
select variable in liste_contenu
do
traitement
done
Si in liste_contenu n’est pas précisé, se sont les paramètres de position qui sont utilisés et affichés.
$ cat select.ksh
!#/usr/bin/ksh
PS3="Votre choix :"
echo "Quelle donnee ?"
select reponse in Jules Romain Francois quitte
do
if [[ "$reponse" = "quitte" ]]
then
break
fi
echo "Vous avez choisi $reponse"
done
echo "Au revoir."
exit 0
$ ./select.ksh
./select.ksh: !#/usr/bin/ksh: not found
Quelle donnee ?
1) Jules
2) Romain
3) Francois
4) quitte
Votre choix :1
Vous avez choisi Jules
Votre choix :3
Vous avez choisi Francois
Votre choix :4
Au revoir.
read et |&
Le Bourne shell ne proposait pas de mécanisme simple pour lire par exemple un fichier ligne à ligne. Le Korn Shell permet d’envoyer le résultat d’une commande dans un tube avec la syntaxe « |& » et de récupérer ce résultat avec la commande read -p.
commande |&
read -p variable
Par exemple, lire un fichier ligne par ligne
$ cat read.ksh
#!/usr/bin/ksh
typeset -i compteur
compteur=1
cat liste |&
while read -p ligne
do
echo "$compteur\t $ligne"
compteur=compteur+1
done
$ ./read.ksh
1 Produit objet prix quantites
2 souris boutons 30 15
3 dur 30giga 100 30
4 dur 70giga 150 30
5 disque zip 12 30
6 disque souple 10 30
7 ecran 15 150 20
8 ecran 17 300 20
9 ecran 19 500 20
10 ecran 21 500 20
11 clavier 105 45 30
12 clavier 115 55 30