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.
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.
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 $