5.3. Tubes

Le mécanisme de tube (symbolisé par le caractère |) permet d’enchaîner l’exécution de commandes successives en connectant la sortie standard d’une commande à l’entrée standard de la commande suivante :

ls -l /bin | more

Il y a affichage du contenu du répertoire /bin (commande ls -l /bin) écran par écran (commande unix more). En effet, les informations affichées par ls -l sont envoyées vers l’entrée de la commande unix more qui les affiche écran par écran. La sortie standard de la dernière commande n’étant pas redirigée, l’affichage final s’effectue à l’écran.

Un résultat équivalent aurait pu être obtenu d’une manière moins élégante en exécutant la suite de commandes :

ls -l /bin >temporaire ; more < temporaire ; rm temporaire

La commande ls -l /bin écrit le résultat dans le fichier temporaire ; ensuite, on affiche écran par écran le contenu de ce fichier ; enfin, on efface ce fichier devenu inutile. Le mécanisme de tube évite à l’utilisateur de gérer ce fichier intermédiaire.

5.3.1. Pipelines

De manière simplifiée, on appelle pipeline, une suite non vide de commandes connectées par des tubes: cmd_1|...|cmd_n

Chaque commande est exécutée par un processus distinct, la sortie standard de la commande cmd_i-1 étant connectée à l’entrée standard de la commande cmd_i.

$ date | tee trace1 trace2 | wc -l
1    => date n’écrit ses résultats que sur une seule ligne
$
$ cat trace1
sam. 08 janv. 2022 21:02:02 CET
$ 
$ cat trace2
sam. 08 janv. 2022 21:02:02 CET
$

La commande unix tee écrit le contenu de son entrée standard sur sa sortie standard tout en gardant une copie dans le ou les fichiers dont on a passé le nom en argument.

Dans l’exemple ci-dessus, tee écrit le résultat de date dans les fichiers trace1 et trace2 ainsi que sur sa sortie standard, résultat passé à la commande wc -l.

5.3.2. Tubes et chaînes jointes

Le shell crée un processus différent pour chaque commande d’un tube cmd1 | cmd2. Cela provoque l’effet suivant : si cmd2 modifie la valeur d’une variable, cette modification disparaitra avec la fin du processus qui exécute cette commande.

$ a=bonjour
$ echo $a | read rep		#  (a)
$ echo $rep				
	=> la variable rep ne contient pas la chaîne bonjour ; elle n’est pas initialisée
$

Si l’on fait afficher la valeur de la variable rep, ligne (a), par le même processus qui a lu la valeur, alors on s’aperçoit que l’affectation a bien été effectuée mais celle-ci disparait avec la fin de ce processus. Pour voir ce comportement, on place les deux commandes à l’intérieur d’une paire de parenthèses (cf. Chapitre 6, Groupement de commandes).

			
$ echo $a | ( read rep ; echo $rep )
bonjour		=> cet affichage montre que l’affectation à rep a bien été effectuée
$
$ echo $rep
	=> variable rep non initialisée
$

Cela provient du fait qu’il y a deux variables rep différentes : une qui est créée et utilisée par le processus qui exécute la commande read rep et une qui est créée et utilisée par le processus qui exécute la commande echo $rep.

L’utilisation d’une chaîne jointe permet de résoudre de manière élégante ce problème de transmission de données entre processus.

$ read rep <<< "$a"
$
$ echo $rep
bonjour
$