両者に
<file.txt tee >(grep LITERAL) >(wc -l) >/dev/null
そして:
{ { <file.txt tee /dev/fd/3 | grep LITERAL >&4; } 3>&1 | wc -l ;} 4>&1
すべてのtee
、grep
そしてwc
同時に開始されています。次に重要なのは、最後に何が起こるかです。
wc
標準入力でファイルの終わりを検出した場合にのみ結果を出力します。最初のケースでtee
は、それtee
が終了するときfd
です。これwc
は、(プロセス置換によって開始された)読み取り元のパイプの反対側で終了するためです。grep
その時間までにすべての入力を読み取り、その出力を書き込んだことは保証されません(パイプがかなりの量のデータを保持でき、それwc
よりも高速である可能性が高いgrep
)
2番目のケースwc
では、読み取り元のパイプへのすべてのライターがパイプの終わりを閉じたときに、ファイルの終わりが表示されます。その場合でも、何人かの作家がいます。tee
(上のFDオープン経由/dev/fd/3
とし、そのFD 3を介して)grep
も、その持っているfd
のパイプにオープン3をwc
(それはそれのいずれかを利用することしていないが、それにのみ書き込みをしましょう)。インナーは{
おそらくもあります余分なサブシェルプロセスが発生しますfd
3オープンにし、両方のを待ちますtee
とをgrep
。
つまりwc
、grep
が終了した後にのみ行番号が書き込まれます。
あなたがそれを適切な方法で書いたなら、それはopenする必要のないfdsを閉じることによってです:
{ { <file.txt tee /dev/fd/3 4>&- |
grep LITERAL >&4 3>&- 4>&-; } 3>&1 | wc -l 4>&-;} 4>&1
その場合、サブシェルプロセスを最適化するシェルでは、順序は保証されません。ただし、私が知っている唯一のシェルはパイプにソケットペアを使用しているksh93
だけなksh93
ので/dev/fd/3
、少なくともLinuxでは動作しません。
プロセスが実行されているかを確認するには、置き換えることができgrep
て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
を使用するとbash
、追加のシェルプロセスを確認でき、次のコマンドを使用してfd 3でパイプが開かれていることも確認できます。
$ (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>&-
、fd 4が使用され、閉じられているように見えますが、どういう意味ですか?