これを反対側に勝ち取らせたい場合は、簡単に行うことができます (tee
特定の順序付けは標準化されているのではなく、実装によって定義されているため、 の同じ実装を使用していると仮定します)。
# note that this uses automatic FD allocation support added in bash 4.1
( exec {orig_stdout}>&1; { tee >(cat >&$orig_stdout) | cat -n; } <<<$'a\nb\nc' )
要するに: tee
(GNU coreutils 8.2.2 で実装されているように) 各行ではなく、各チャンクを書き込みます。の POSIX 仕様では、tee
行指向の出力バッファリングが明示的に禁止されています。最初は標準出力へ、次に各引数へ、左から右へ。
実装でそれを見ることができます:
/* Move all the names 'up' one in the argv array to make room for
the entry for standard output. This writes into argv[argc]. */
for (i = nfiles; i >= 1; i--)
files[i] = files[i - 1];
...次にdescriptors
、 の配列エントリを使用して 1:1 でマッピングされた配列files
を作成し、それぞれに順番に書き込みます。
/* Write to all NFILES + 1 descriptors.
Standard output is the first one. */
for (i = 0; i <= nfiles; i++)
if (descriptors[i]
&& fwrite (buffer, bytes_read, 1, descriptors[i]) != 1)
これが競合ではなく一貫した動作になるように実装される理由を説明すると、tee の POSIX 仕様では、入力をバッファリングしないことが要求されています。したがって、順序は各記述子への書き込み間で維持される必要があります (もちろん、後でパイプライン内の項目がそれ自体をバッファリングする場合、順序はその時点以降に失われる可能性があります)。
現在: これは、次の場所に進む前に完全な入力を各場所にコピーするということではありません。tee
むしろ、tee はBUFSIZ
それぞれバイトのブロックで動作します。ここで、BUFSIZ
は 256 バイト以上であることが保証されているオペレーティング システム固有の定数であり、最近の (組み込みではない) Linux では 8K 付近で頻繁に動作します。したがって、非常に大きな入力を使用すると、期待どおりにインターリーブが表示されますが、上記の理由により、一貫した順序で表示されます。