你怎么能区分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和销毁的(不像临时文件)。
有些人到达这个页面可能正在寻找逐行比较,为此应该使用comm
或grep -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
。