Toutes les commandes que nous nous avons vu jusqu’à présent sont standards et ne sont pas propres à un shell particulier. Avant d’entamer la programmation shell elle-même, il nous faut voir quelques options détaillées du shell par défaut, le Bourne Shell.

Fichier de configuration

Le Bourne Shell dispose d’un fichier de configuration chargé et exécuté lors du lancement du shell. Il est généralement placé dans le répertoire par défaut de l’utilisateur et se nomme .profile.

PATH=/home/oracle/bin:$ORACLE_HOME/bin:/usr/sbin:/usr/local/bin:/usr/bin:/sqlbt/datatools/obacktrack/bin:/usr/opt/networker/bin:.
#export NLS\_SORT=BINARY
#. /usr/local/bin/oraenv
umask 022

Commandes internes et externes

Une commande peut être interne ou externe. Une commande interne est une commande directement incluse et interprétée par le shell, sans passer par un quelconque exécutable. Un exemple est la commande cd.

Une commande externe est un exécutable que le shell recherchera dans une liste de chemins prédéfinis, le PATH, puis exécutera en tant que processus fils.

D’autres mécanismes existent, comme les fonctions et les alias (hors Bourne Shell), que nous aborderons plus tard.

Herescript

La redirection « << » n’a pas été abordée car elle est particulière. Elle permet l’utilisation des Herescripts (Script ici). Un herescript permet la saisie d’un texte jusqu’à un point donné et l’envoi de son résultat à une commande ou un filtre. Les redirections classiques sont aussi autorisées. Après le « << » on indique une chaîne définissant la fin de saisie, par exemple ici end.

$ tr "[a-z]" "[A-Z]" << end
> bonjour les amis
> ceci est un exemple
> de herescript
> end
BONJOUR LES AMIS
CECI EST UN EXEMPLE
DE HERESCRIPT

Ouverture de canaux

Les canaux standards sont au nombre de trois et numérotés de 0 à 2. Ainsi 0< équivaut à < et 1> à >. La commande exec permet d’ouvrir sept autres canaux numérotés de 3 à 9. On a donc en tout dix canaux.

On peut envisager, dans le cadre de traitements, de sortir certains résultats par le canal 3, d’autres par le 4, et ainsi de suite. Les canaux ouvert le sont en entrée et en sortie.

$ exec num_canal > fichier_ou_reunion
$ exec 3>dump.log
$ ls -l >&3
$ cat dump.log
total 5716
-rw-r--r--   1 oracle   system            0 Aug 14 15:55 dump.log
-rwxr-xr-x   1 oracle   dba               0 Aug 12 11:05 fic1
-rw-r--r--   4 oracle   system            0 Aug 12 11:05 fic2
-rw-r-----   1 oracle   dba               0 Aug 12 11:05 fic3
-rw-r--r--   1 oracle   system           33 Aug 12 12:03 fic4
-rw-r--r--   4 oracle   system            0 Aug 12 11:05 hardlink2_fic2
-rw-r--r--   4 oracle   system            0 Aug 12 11:05 hardlink3_fic2
-rw-r--r--   4 oracle   system            0 Aug 12 11:05 hardlink_fic2
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          252 Aug 12 14:30 liste
-rw-r--r--   1 oracle   system          234 Aug 13 10:06 liste2
-rw-r--r--   1 oracle   system      4829707 Aug 14 11:23 liste_ls
-rw-r--r--   1 oracle   system       974408 Aug 13 15:20 ls.txt
-rw-r--r--   1 oracle   system         4010 Aug 13 09:10 mypass
-rw-------   1 oracle   system          106 Aug 14 11:09 nohup.out
drwxr-xr-x   2 oracle   dba            8192 Aug 12 11:21 rep1
drwxr-xr-x   2 oracle   system         8192 Aug 14 14:16 rep2
drwxr-xr-x   2 oracle   system         8192 Aug 14 14:17 seb1
drwxr-xr-x   2 oracle   system         8192 Aug 14 14:17 seb2
-rw-r--r--   1 oracle   system         2564 Aug 13 13:45 toto.tar.gz
-rw-r--r--   1 oracle   system          402 Aug 13 09:33 users

Tous ce qui sera écrit dans le canal 3 sera écrit dans le fichier dump.log. On peut ensuite fermer le canal en le réunissant avec un pseudo-canal (canal de fermeture -).

$ exec 3>&-

Groupement de commandes

Nous avons vu que le chaînage de commande est possible avec le ;. Il est aussi possible de grouper les commandes. Quand on exécute les commandes suivantes :

$ uname -a ; pwd ; ls -l >resultat.txt &

seule la dernière commande est exécutée en tâche de fond et seul son résultat est redirigé dans le fichier resultat.txt. Une solution serait :

$ uname -a >resultat.txt & ; pwd >> resultat.txt & ; ls -l >> resultat.txt &
[1] 18232
[2] 18238
[3] 18135

C’est une solution complexe et qui ne marchera pas toujours. De plus même si les commandes sont lancées séquentiellement, elles tournent toutes en parallèle et c’est la première finie qui écrira en premier dans le fichier. La solution consiste en l’utilisation des parenthèses ( ).

$ (uname -a ; pwd ; ls -l) > resultat.txt &
[1] 18239
$
[1]    Done                   ( uname -a; pwd; ls -l ) > resultat.txt

Dans ce cas, toutes les commandes placées entre les parenthèses sont lancées par un sous-shell, qui va ensuite exécuter les commandes précisées séquentiellement telles qu’indiquées. Ainsi la redirection concerne l’ensemble des commandes et rien n’empêche de lancer ce sous-shell en arrière-plan. On distingue bien d’ailleurs un seul PID 18239 lors de l’exécution des commandes.

Une seconde possibilité est l’utilisation des accolades {...}. Dans ce cas aucun sous-shell n’est exécuté, et si une commande interne (cd ou autre) est exécutée, elle concerne le shell actif. L’accolade fermante doit être placée juste après un ;.

$ { uname -a; pwd; ls -l; } > resultat.txt

Liaison et exécution conditionnelle

En plus du chaînage classique, les commandées peuvent être liées et exécutées de façon conditionnelle. La condition d’exécution d’une commande est la réussite ou non de la précédente.

Chaque commande une fois exécutée sort un code retour, généralement 0 si tout s’est bien passé, 1 ou 2 en cas d’erreur. Le shell peut récupérer cette valeur par la variable $#.

(Les variables seront abordées plus en détail dans le chapitre de Programmation Shell).

$ ls
...
$ echo $?
0

Les caractères « && » et « || » permettent d’effectuer une exécution conditionnelle.

commande1 && commande2
commande1 || commande2

La commande située après « && » sera exécutée uniquement si la commande précédente a retourné 0 (réussite). La commande située après « || » ne sera exécutée que si la commande précédente a retourné autre chose que 0.

$ cat liste
Produit objet   prix    quantites
souris  optique 30      15
dur     30giga  100     30
dur     70giga  150     30
disque  zip     12      30
disque  souple  10      30
ecran   15      150     20
ecran   17      300     20
ecran   19      500     20
clavier 105     45      30
clavier 115     55      30
carte   son     45      30
carte   video   145     30
$ (grep "souris" liste && echo "Souris trouvee") || echo "Souris introuvable"
souris  optique 30      15
Souris trouvee
$ (grep "memoire" liste && echo "Memoire trouvee") || echo "Memoire introuvable"
Memoire introuvable

Photo récupérée de bashlogo.com