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

print

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