Sowohl
<file.txt tee >(grep LITERAL) >(wc -l) >/dev/null
Und:
{ { <file.txt tee /dev/fd/3 | grep LITERAL >&4; } 3>&1 | wc -l ;} 4>&1
Alle tee
, grep
und wc
werden gleichzeitig gestartet. Was dann zählt, ist was am Ende passiert.
wc
druckt das Ergebnis nur, wenn das Dateiende auf seiner Standardeingabe angezeigt wird. Im ersten Fall, das ist , wenn tee
Ausfahrten, weil dann tee
seine schließen wird fd
am anderen Ende des Rohres , das wc
aus (Gestartet von Prozess - Substitution) liest. Dafür gibt es keine Garantiegrep
bis zu diesem Zeitpunkt alle Eingaben gelesen wurden, geschweige denn die Ausgaben geschrieben wurden (da Pipes eine ziemlich große Datenmenge aufnehmen können und dies wc
wahrscheinlich schneller sein wird als grep
).
Im zweiten Fall wc
wird das Dateiende angezeigt, wenn alle Schreiber der Pipe, von der gelesen wird, ihr Pipe-Ende geschlossen haben. In diesem Fall gibt es jedoch mehrere Autoren. tee
(über sein fd open on /dev/fd/3
und über sein fd 3) und grep
das auch seine fd
3 offen für das Rohr hat wc
(obwohl es es nicht benutzt, geschweige denn darauf schreibt). Das Innere {
wird wahrscheinlich einen zusätzlichen Subshell-Prozess verursachen, bei dem auch eine fd
3 geöffnet ist und auf beide tee
und gewartet wird grep
.
Das bedeutet, dass wc
die Zeilennummer erst nach dem grep
Beenden geschrieben wird.
Hatten Sie es richtig geschrieben, indem Sie die FDS geschlossen haben, die nicht geöffnet werden mussten:
{ { <file.txt tee /dev/fd/3 4>&- |
grep LITERAL >&4 3>&- 4>&-; } 3>&1 | wc -l 4>&-;} 4>&1
Dann wäre die Reihenfolge in Shells, die den Subshell-Prozess optimieren, nicht garantiert worden. Die einzige Shell, die ich kenne, ist ksh93
aberksh93
Verwendungen Buchsenpaare für Rohre, so /dev/fd/3
wird nicht da zumindest unter Linux arbeiten.
Um zu sehen , welche Prozesse ausgeführt werden , können Sie ersetzen grep
mit 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
Mit bash
können Sie diesen zusätzlichen Shell-Prozess sehen, und Sie können sehen, dass auch die Pipe auf fd 3 geöffnet ist mit:
$ (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>&-
dass der fd 4 sowohl verwendet als auch geschlossen zu sein scheint?>&4
, kurz für1>&4
,grep
fd 1 und 4 zeigen auf dieselbe Ressource (die anfängliche Standardausgabe der Shell).grep
muss seine fd 4 für nichts offen haben. Es macht nichts damit, also schließen wir es mit4>&-
Um eine vorhersehbare Bestellung zu erhalten, verwenden Sie
quelle