À la fois
<file.txt tee >(grep LITERAL) >(wc -l) >/dev/null
Et:
{ { <file.txt tee /dev/fd/3 | grep LITERAL >&4; } 3>&1 | wc -l ;} 4>&1
Tous tee
, grep
et wc
sont mises en marche en même temps. Ce qui compte alors, c'est ce qui se passe à la fin.
wc
n'imprimera le résultat que lorsqu'il verra la fin du fichier sur son entrée standard. Dans le premier cas, c'est à ce moment tee
-là que tee
se termine , car alors il se fermera fd
à l'autre extrémité du tuyau en cours de wc
lecture (démarré par substitution de processus). Il n'y a aucune garantie qui grep
aura lu toutes ses entrées à ce moment-là, et encore moins écrit sa sortie (étant donné que les tuyaux peuvent contenir une quantité assez importante de données et qui wc
sera probablement plus rapide que grep
)
Dans le second cas, la wc
fin du fichier s'affiche lorsque tous les rédacteurs du tuyau en cours de lecture ont fermé l'extrémité du tuyau. Dans ce cas cependant, il y a plusieurs écrivains. tee
(via son fd ouvert sur /dev/fd/3
et via son fd 3) et grep
qui a également son fd
3 ouvert au tuyau wc
(même s'il n'en fait aucun usage, et encore moins lui écrit). L'intérieur {
provoquera probablement un processus de sous-shell supplémentaire qui aura également un fd
3 ouvert et attendra les deux tee
et grep
.
Cela signifie que wc
n'écrira son numéro de ligne qu'après grep
sa sortie.
Si vous l'aviez écrit de la bonne façon, c'est-à-dire en fermant les fds qui n'avaient pas besoin d'être ouverts:
{ { <file.txt tee /dev/fd/3 4>&- |
grep LITERAL >&4 3>&- 4>&-; } 3>&1 | wc -l 4>&-;} 4>&1
La commande n'aurait alors pas été garantie dans des coques qui optimisent le processus de sous-coque. Cependant, la seule coquille que je sais que cela n'est , ksh93
mais ksh93
utilise un socket paires pour les tuyaux, donc /dev/fd/3
ne fonctionnera pas là sur Linux au moins.
Pour voir quels processus sont en cours d'exécution, vous pouvez remplacer grep
par ps
:
$ { { <file.txt tee /dev/fd/3 4>&- | ps -H >&4 3>&- 4>&-; } 3>&1 | wc -l 4>&-;} 4>&1
PID TTY TIME CMD
8727 pts/5 00:00:00 bash
8815 pts/5 00:00:00 bash
8817 pts/5 00:00:00 tee
8818 pts/5 00:00:00 ps
8816 pts/5 00:00:00 wc
Avec bash
, vous pouvez voir ce processus de shell supplémentaire, et vous pouvez également voir que le tuyau est ouvert sur fd 3 avec:
$ (p=$BASHPID; { { <file.txt tee /dev/fd/3 4>&- | lsof -ag "$p" -d3 >&4 3>&- 4>&-; } 3>&1 | wc -l 4>&-;} 4>&1)
COMMAND PID PGID USER FD TYPE DEVICE SIZE/OFF NODE NAME
bash 9843 9842 chazelas 3w FIFO 0,8 0t0 153304 pipe
tee 9845 9842 chazelas 3w FIFO 0,8 0t0 153304 pipe
lsof 9846 9842 chazelas 3r DIR 0,3 0 1 /proc
grep LITERAL >&4 3>&- 4>&-
signifie, le fd 4 semble être à la fois utilisé et fermé?>&4
, abréviation de1>&4
,grep
les fd 1 et 4 pointent vers la même ressource (la sortie standard du shell).grep
n'a pas besoin d'avoir son fd 4 ouvert à quoi que ce soit. Il ne fait rien avec ça, donc on ferme avec4>&-
Pour obtenir une commande prévisible, utilisez
la source