Answers:
命令替换`…`
将命令的输出替换为命令行,因此diff
将两个目录中的文件列表都视为参数。您要diff
在命令行上看到两个文件名,并将这些文件的内容作为目录列表。这就是流程替代的作用。
diff <(ls old) <(ls new)
的参数diff
将类似于/dev/fd/3
和/dev/fd/4
:它们是与bash创建的两个管道相对应的文件描述符。当diff
打开这些文件时,它会连接到每个管道的读取端。每个管道的写端都连接到ls
命令。
echo <(echo) <(echo)
从来没有想过这可能会如此有趣:D
ls
是它会处理文件名。解析其输出很脆弱(不适用于“怪异”文件名)。对于比较两个目录列表,只要输出是明确的就可以。对于任意文件名,这将需要一个选项,例如--quoting-style=escape
。
<(…)
创建一个管道。似乎meld不适用于管道,因此您不能使用<(…)
。在zsh中,您可以替换<(…)
为=(…)
并且它将起作用,因为=(…)
将中间输出放置在临时文件中。在bash中,我认为没有任何方便的语法,您必须自己管理临时文件。
对于zsh,使用会=(command)
自动创建一个临时文件,并替换=(command)
为文件本身的路径。使用Command Substitution,$(command)
将替换为命令的输出。
因此,有三种选择:
$(...)
<(...)
=(...)
zsh风格的进程替换#3非常有用,可以像这样使用diff工具比较两个命令的输出,例如Beyond Compare:
bcomp =(ulimit -Sa | sort) =(ulimit -Ha | sort)
对于“超越比较”,请注意,由于启动了比较并等待其完成,因此您必须使用bcomp
以上(而不是bcompare
)。如果使用,则会启动比较并立即退出,因此,用于存储命令输出的临时文件将消失。bcomp
bcompare
在此处阅读更多信息:http: //zsh.sourceforge.net/Intro/intro_7.html
另请注意:
请注意,外壳程序会创建一个临时文件,并在命令完成后将其删除。
以下是zsh支持的两种类型的进程替换之间的区别(即#2和#3):
如果阅读zsh的手册页,您可能会注意到<(...)是另一种过程替换形式,类似于=(...)。两者之间有重要区别。在<(...)的情况下,外壳程序将创建一个命名管道(FIFO)而不是文件。这样做会更好,因为它不会填满文件系统。但并非在所有情况下都有效。实际上,如果在上面的示例中用<(...)替换了=(...),除了fgrep -f <(...)以外,所有其他代码都将停止工作。您不能编辑管道,也不能将其作为邮件文件夹打开。但是,fgrep从管道中读取单词列表没有问题。您可能想知道为什么diff <(foo)bar不起作用,因为foo | diff-酒吧工作;这是因为diff如果注意到它的参数之一是-,就会创建一个临时文件,然后将其标准输入复制到该临时文件中。
参考:https://unix.stackexchange.com/questions/393349/difference-between-subshells-and-process-substitution
$(...)
不是进程替代,而是命令替代。<(...)
是流程替代。这就是为什么引用的段落根本没有提及$(...)
。
在Fish shell中,您必须将其放入psub中。这是一个用Beyond Compare比较 heroku和dokku配置的示例:
bcompare (ssh me@myapp.pl dokku config myapp | sort | psub) (heroku config -a myapp | sort | psub)
meld
开源的,可在Ubuntu和EPEL存储库中使用。meldmerge.org
我经常使用公认的答案中描述的技术:
diff <(ls old) <(ls new)
但是我发现我通常使用比上面的示例复杂得多的命令。在这种情况下,制作diff命令可能很烦人。我提出了一些可能对其他人有用的解决方案。
我发现在运行diff之前,我有99%的时间尝试了相关命令。因此,我想比较的命令就在我的历史中……为什么不使用它们呢?
我利用内置的Fix Command(fc)bash来执行最后两个命令:
$ echo A
A
$ echo B
B
$ diff --color <( $(fc -ln -1 -1) ) <( $(fc -ln -2 -2 ) )
1c1
< B
---
> A
fc标志是:
-n:没有数字。列出时禁止显示命令编号。
-l:列出:命令在标准输出上列出。
该-1
-1
指开始和结束在:放置的历史,到产生最后那个命令的最后一个命令这种情况下它从最后的命令。
最后,我们将其包装起来$()
以在子shell中执行命令。
显然,这有点麻烦,所以我们可以创建一个别名:
alias dl='diff --color <( $(fc -ln -1 -1) ) <( $(fc -ln -2 -2 ) )'
或者我们可以创建一个函数:
dl() {
if [[ -z "$1" ]]; then
first="1"
else
first="$1"
fi
if [[ -z "$2" ]]; then
last="2"
else
last="$2"
fi
# shellcheck disable=SC2091
diff --color <( $(fc -ln "-$first" "-$first") ) <( $(fc -ln "-$last" "-$last") )
}
支持指定要使用的历史记录行。两者都使用后,我发现别名是我喜欢的版本。