来自两个程序的差异输出,没有临时文件


Answers:


211

使用<(command)一个命令的输出传递到另一个程序,就好像它是一个文件名。Bash将程序的输出通过管道传输到管道,然后将文件名传递/dev/fd/63给外部命令。

diff <(./a) <(./b)

同样,>(command)如果要将管道中的内容传送命令中,也可以使用。

在Bash的手册页中,这称为“流程替换”。


1
要注意的一个缺点是,如果./a或./b失败,则调用者将不会发现该错误。
Alexander Pogrebnyak

5
OP确实标记了问题bash,但为了记录起见,这在任何其他shell中均不起作用。它是Posix实用程序标准的bash扩展。
DigitalRoss

5
我使用Java程序尝试了此解决方案,但收到此错误:-bash: syntax error near unexpected token ('。我再次尝试,没有括号,但得到了-bash: java: No such file or directory。如果命令有参数,它不起作用吗?
styfle

1
@DigitalRoss-解决方案可以使用别名扩展到其他外壳。在tcsh中,以下丑陋的作品: alias diffcmd bash -c \'diff \<\(sh -c \!:1\) \<\( sh -c \!:2 \)\'。(然后,例如:diffcmd“ ls”“ ls -a”)。
保罗·林奇

对于任何在Google之外徘徊的人,这在zsh下也适用。(此外,如果您需要将输入内容输入到调用中fseek,zsh提供的=(./a)内容可以与zsh 完全一样地<(./a)使用,但在
后台

26

将两个答案加在一起,如果要查看并排比较,请使用vimdiff

vimdiff <(./a) <(./b)

像这样:

在此处输入图片说明


vimdiff创建美观,智能和交互式的差异比较视图。该vim软件包似乎在大多数系统上都附带。
TimVisée17年

vimdiff还不仅显示不同的行,而且显示不同的特定文本片段。
安东·塔拉申科


15

对于任何好奇的人,这是使用Fish Shell进行过程替换的方式:

重击:

diff <(./a) <(./b)

鱼:

diff (./a | psub) (./b | psub)

不幸的是鱼的执行目前缺乏的 ; fish将挂起或使用磁盘上的临时文件。您也不能将psub用于命令的输出。


目前,这在鱼类中无法正常工作。如果程序的输出大于一个BUFSIZ,该命令将挂起。(否则fish实际上只会使用磁盘上的临时文件)
Evan Benn

7

在已经很好的答案中添加更多内容(对我有所帮助!):

该命令将docker其帮助输出到STD_ERR(即文件描述符2)

我想看看是否docker attachdocker attach --help给出了相同的输出

$ docker attach

$ docker attach --help

刚刚键入这两个命令后,我执行了以下操作:

$ diff <(!-2 2>&1) <(!! 2>&1)

!! 与!-1相同,表示在此命令之前运行命令1-最后一个命令

!-2表示在此命令之前运行两个命令

2>&1表示将file_descriptor 2输出(STD_ERR)发送到与file_descriptor 1输出(STD_OUT)相同的位置

希望这已经有用。


0

对于zsh,使用会=(command)自动创建一个临时文件,并替换=(command)为文件本身的路径。对于正常的Process Substitution,$(command)将替换为命令的输出

这个zsh功能非常有用,可以像使用diff工具一样比较两个命令的输出,例如Beyond Compare:

bcomp  =(ulimit -Sa | sort) =(ulimit -Ha | sort)

对于“超越比较”,请注意,由于必须启动比较并等待其完成,因此您必须使用bcomp上面的(而不是bcompare)。如果使用,则会启动比较并立即退出,因此,用于存储命令输出的临时文件将消失。bcompbcompare

在此处阅读更多信息:http: //zsh.sourceforge.net/Intro/intro_7.html

另请注意:

请注意,外壳程序会创建一个临时文件,并在命令完成后将其删除。

并且其之间的差以下$(...)=(...)

如果阅读zsh的手册页,您可能会注意到<(...)是另一种过程替换形式,类似于=(...)。两者之间有重要区别。在<(...)的情况下,外壳程序将创建一个命名管道(FIFO)而不是文件。这样做会更好,因为它不会填满文件系统。但并非在所有情况下都有效。实际上,如果在上面的示例中用<(...)将=(...)替换为<(...),则除了fgrep -f <(...)外,所有其他代码都将停止工作。您不能编辑管道,也不能将其作为邮件文件夹打开。但是,fgrep从管道中读取单词列表没有问题。您可能想知道为什么diff <(foo)bar不起作用,因为foo | diff-酒吧工作;这是因为diff如果注意到它的参数之一是-,则会创建一个临时文件,然后将其标准输入复制到该临时文件中。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.