包含 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 设置的已打开文件描述符中读取在执行命令之前启动。(即 bashpipe(2)
在 fork 之前使用,然后在 fd 63 上dup2
从 的输出重定向quux
到 的输入文件描述符diff
。)
在没有“神奇” /dev/fd
or的系统上/proc/self/fd
,bash 可能会使用命名管道来实现进程替换,但与临时文件不同,它至少会自己管理它们,并且您的数据不会被写入文件系统。
您可以检查 bash 如何实现进程替换echo <(true)
以打印文件名而不是从中读取文件名。/dev/fd/63
它在典型的 Linux 系统上打印。或者有关 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