Zarówno
<file.txt tee >(grep LITERAL) >(wc -l) >/dev/null
I:
{ { <file.txt tee /dev/fd/3 | grep LITERAL >&4; } 3>&1 | wc -l ;} 4>&1
Wszystko tee, grepi wcsą uruchamiane jednocześnie. Liczy się to, co stanie się na końcu.
wcwypisze wynik tylko wtedy, gdy zobaczy koniec pliku na swoim standardowym wejściu. W pierwszym przypadku następuje teewyjście, ponieważ wtedy teezamknie fdsię na drugim końcu potoku, który wcczyta (rozpoczęte przez podstawienie procesu). Nie ma gwarancji, że do greptego czasu przeczyta wszystkie dane wejściowe, nie mówiąc już o zapisaniu danych wyjściowych (biorąc pod uwagę, że potoki mogą przechowywać dość dużą ilość danych, a to wcprawdopodobnie będzie szybsze niż grep)
W drugim przypadku, wczobaczysz koniec pliku, gdy wszyscy piszący do potoku, z którego on czyta, zamknęli swój koniec potoku. W takim przypadku jest jednak kilku pisarzy. tee(przez jego fd otwarty na /dev/fd/3i przez jego fd 3), grepktóry również ma swój fd3 otwarty na potok do wc(chociaż nie korzysta z niego, nie mówiąc już o napisaniu do niego). Wewnętrzny {prawdopodobnie spowoduje dodatkowy proces podpowłoki, który również będzie miał fd3 otwarte i będzie czekać na oba teei grep.
Oznacza to, że wczapisze numer linii dopiero po grepwyjściu.
Czy napisałeś to we właściwy sposób, to znaczy zamykając fds, które nie wymagały otwarcia:
{ { <file.txt tee /dev/fd/3 4>&- |
grep LITERAL >&4 3>&- 4>&-; } 3>&1 | wc -l 4>&-;} 4>&1
Wtedy kolejność nie byłaby zagwarantowana w powłokach, które optymalizują proces podpowłoki. Jednak jedyną powłoką, którą znam, jest to, ksh93że ksh93korzysta z par gniazd dla potoków, więc /dev/fd/3nie będzie tam działać przynajmniej w systemie Linux.
Aby zobaczyć, jakie procesy są uruchomione, można wymienić grepz 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
Za pomocą bash, możesz zobaczyć ten dodatkowy proces powłoki, i możesz zobaczyć, że ma również otwartą rurkę na fd 3 z:
$ (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>&-oznacza, że fd 4 wydaje się być używany i zamknięty?