一行包含 2 个 tmp 文件(不是您想要的):
foo | bar > file1.txt && baz | quux > file2.txt && diff file1.txt file2.txt
使用 bash,您可以尝试:
diff <(foo | bar) <(baz | quux)
foo | bar | diff - <(baz | quux) # or only use process substitution once
第二个版本会更清楚地提醒您哪个输入是哪个,通过显示
-- /dev/stdin vs. ++ /dev/fd/63 或其他东西,而不是两个编号的 fd。
文件系统中甚至不会出现命名管道,至少在 bash 可以通过使用 /dev/fd/63 之类的文件名来实现进程替换的操作系统上,以获取命令可以打开和读取的文件名,以实际读取已经 -打开 bash 在执行命令之前设置的文件描述符。 (即 bash 在 fork 之前使用 pipe(2),然后使用 dup2 从 quux 的输出重定向到 diff 的输入文件描述符,在 fd 63 上。)
在没有“神奇”/dev/fd 或 /proc/self/fd 的系统上,bash 可能会使用命名管道来实现进程替换,但与临时文件不同,它至少会自己管理它们,并且不会写入您的数据到文件系统。
您可以检查 bash 如何使用 echo <(true) 实现进程替换以打印文件名而不是从中读取文件名。它在典型的 Linux 系统上打印 /dev/fd/63。或者要详细了解 bash 使用的系统调用,Linux 系统上的这个命令将跟踪文件和文件描述符系统调用
strace -f -efile,desc,clone,execve bash -c '/bin/true | diff -u - <(/bin/true)'
没有 bash,您可以创建命名管道。使用- 告诉diff 从STDIN 读取一个输入,并将命名管道用作另一个:
mkfifo file1_pipe.txt
foo|bar > file1_pipe.txt && baz | quux | diff file1_pipe.txt - && rm file1_pipe.txt
请注意,您只能使用 tee 命令将 一个输出 传递到 多个输入:
ls *.txt | tee /dev/tty txtlist.txt
以上命令将ls *.txt的输出显示到终端,并输出到文本文件txtlist.txt。
但是通过进程替换,您可以使用tee 将相同的数据提供给多个管道:
cat *.txt | tee >(foo | bar > result1.txt) >(baz | quux > result2.txt) | foobar