我曾想过,比较两个相似目录内容的最简单方法是这样的
diff `ls old` `ls new`
但我明白为什么这不起作用;diff
在命令行上传递的是一大串文件,而不是像我希望的那样传递两个流。我如何将两个输出直接传递给 diff?
答案1
命令替换`…`
将命令的输出替换到命令行中,因此diff
将两个目录中的文件列表视为参数。您想要的是diff
在其命令行上看到两个文件名,并将这些文件的内容作为目录列表。这就是流程替代做。
diff <(ls old) <(ls new)
的参数diff
看起来像/dev/fd/3
和/dev/fd/4
:它们是 bash 创建的两个管道对应的文件描述符。diff
打开这些文件时,它将连接到每个管道的读取端。每个管道的写入端连接到命令ls
。
答案2
鱼壳
在 Fish shell 中,你必须输入韓輯。以下是 heroku 和 dokku 配置比较的示例无可比拟:
bcompare (ssh [email protected] dokku config myapp | sort | psub) (heroku config -a myapp | sort | psub)
答案3
对于 zsh,使用=(command)
会自动创建一个临时文件并替换=(command)
为文件本身的路径。使用命令替换,$(command)
会替换为输出该命令。
因此,有三个选择:
- 命令替换:
$(...)
- 流程替代:
<(...)
- zsh 风格的进程替换:
=(...)
zsh 风格的进程替换,#3,非常有用,可以像这样使用 diff 工具比较两个命令的输出,例如 Beyond Compare:
bcomp =(ulimit -Sa | sort) =(ulimit -Ha | sort)
对于 Beyond Compare,请注意,您必须使用bcomp
上面的(而不是bcompare
),因为bcomp
启动比较和等待才能完成。如果您使用bcompare
,则会启动比较并立即退出,因此为存储命令输出而创建的临时文件会消失。
更多详情请阅读:http://zsh.sourceforge.net/Intro/intro_7.html
还请注意:
请注意,shell 会创建一个临时文件,并在命令完成时将其删除。
以下是 zsh 支持的两种进程替换类型(即 #2 和 #3)之间的区别:
如果您阅读 zsh 的手册页,您可能会注意到 <(...) 是另一种进程替换形式,类似于 =(...)。两者之间有一个重要的区别。在 <(...) 的情况下,shell 会创建一个命名管道 (FIFO) 而不是文件。这样更好,因为它不会填满文件系统;但它并非在所有情况下都有效。事实上,如果我们在上面的例子中用 <(...) 替换 =(...),除了 fgrep -f <(...) 之外,所有例子都会停止工作。您无法编辑管道,也无法将其作为邮件文件夹打开;但是,fgrep 可以从管道读取单词列表。您可能想知道为什么 diff <(foo) bar 不起作用,因为 foo | diff - bar 可以工作;这是因为如果 diff 注意到它的一个参数是 -,它会创建一个临时文件,然后将其标准输入复制到临时文件。
答案4
我经常使用接受的答案中描述的技术:
diff <(ls old) <(ls new)
但我发现我通常将它用于比上述示例更复杂的命令。在这种情况下,编写 diff 命令可能会很烦人。我想出了一些其他人可能会觉得有用的解决方案。
我发现 99% 的时间我都会在运行 diff 之前尝试相关命令。因此,我想要 diff 的命令就在我的历史记录中... 为什么不使用它们呢?
我利用 bash 内置的 Fix Command (fc) 来执行最后两个命令:
$ 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") )
}
它支持指定要使用的历史记录行。使用过两者后,我发现别名是我喜欢的版本。