你怎么能区分Bash中的两个pipe道?

如何在Bash中不使用临时文件来区分两个pipe道? 假设你有两个命令pipe道:

foo | bar baz | quux 

而你想在他们的输出中finddiff 。 一个解决办法显然是:

 foo | bar > /tmp/a baz | quux > /tmp/b diff /tmp/a /tmp/b 

有没有可能在Bash中使用临时文件? 您可以通过在其中一个pipe道中pipe道来摆脱一个临时文件来区分:

 foo | bar > /tmp/a baz | quux | diff /tmp/a - 

但是,你不能同时把两个pipe道同时pipe入diff(至less没有任何明显的方式)。 涉及/dev/fd有没有使用临时文件做这个巧妙的伎俩?

一行2 tmp文件(不是你想要的)将是:

  foo | bar > file1.txt && baz | quux > file2.txt && diff file1.txt file2.txt 

bash ,你可以尝试:

  diff <(foo | bar) <(baz | quux) 

正如BenM的详细解答中提到的 , <创build匿名命名pipe道 – 由bashpipe理 – 所以它们是自动创build和销毁的,与临时文件不同。
然而, 丹尼尔·卡西迪指出,“不使用临时文件”部分的问题是不被尊重的:文件系统仍然被修改(用一个目录条目代表创build的命名pipe道,然后删除)

否则,就像你提到你的问题,你必须使用 – 作为STDIN

  foo | bar > file1.txt && baz | quux | diff file1.txt - && rm file1.txt 

,因为似乎没有简单的方法来pipe多个input到一个命令。

您只能使用tee命令将一个输出输出多个input

 ls *.txt | tee /dev/tty txtlist.txt 

以上命令显示ls * .txt到terminal的输出并将其输出到文本文件txtlist.txt。

在bash中,可以使用子壳体,通过将pipe道封闭在括号内来单独执行命令pipe道。 然后你可以用<作为前缀来创build匿名的命名pipe道,然后你可以传入diff。

例如:

 diff <(foo | bar) <(baz | quux) 

匿名命名pipe道是由bashpipe理的,所以它们是自动创build和销毁的(不像临时文件)。

有些人到达这个页面可能正在寻找逐行比较,为此应该使用commgrep -f

有一件事要指出的是,在所有的答案的例子中,差异不会真正开始,直到两个stream都完成。 testing这个例如:

 comm -23 <(seq 100 | sort) <(seq 10 20 && sleep 5 && seq 20 30 | sort) 

如果这是一个问题,你可以尝试不需要sorting的sd (stream diff),也不需要象上面的例子那样处理replace,而是比grep -f快或者更快,并支持无限stream。

我build议的testing例子会在sd这样写:

 seq 100 | sd 'seq 10 20 && sleep 5 && seq 20 30' 

但不同之处在于, seq 100会和seq 10马上分开。 请注意,如果其中一个stream是tail -f ,那么diff就不能通过进程replace完成。

这里是我写的关于在terminal上引入sd的terminalstream分类的sd