Ter*_*ary 230 command-line diff
我曾想象比较两个相似目录的内容的最简单方法是
diff `ls old` `ls new`
Run Code Online (Sandbox Code Playgroud)
但我明白为什么这不起作用;diff
在命令行上收到一长串文件,而不是我希望的两个流。如何将两个输出直接传递给 diff?
Gil*_*il' 333
命令替换`…`
将命令的输出替换到命令行中,因此diff
将两个目录中的文件列表视为参数。您想要的是diff
在其命令行上看到两个文件名,并将这些文件的内容作为目录列表。这就是进程替换的作用。
diff <(ls old) <(ls new)
Run Code Online (Sandbox Code Playgroud)
的参数diff
看起来像/dev/fd/3
和/dev/fd/4
:它们是对应于 bash 创建的两个管道的文件描述符。当diff
打开这些文件时,它将连接到每个管道的读取端。每个管道的写入端都连接到ls
命令。
Woo*_*Yek 10
在 Fish shell 中,您必须通过管道输入psub。以下是使用Beyond Compare 比较heroku 和 dokku 配置的示例:
bcompare (ssh me@myapp.pl dokku config myapp | sort | psub) (heroku config -a myapp | sort | psub)
Run Code Online (Sandbox Code Playgroud)
我经常使用已接受答案中描述的技术:
diff <(ls old) <(ls new)
Run Code Online (Sandbox Code Playgroud)
但我发现我通常将它与比上面的示例复杂得多的命令一起使用。在这种情况下,制作 diff 命令可能会很烦人。我提出了一些其他人可能会觉得有用的解决方案。
我发现 99% 的情况下我会在运行 diff 之前尝试相关命令。因此,我想要比较的命令就在我的历史记录中......为什么不使用它们呢?
我使用内置的 Fix Command (fc) bash 来执行最后两个命令:
$ echo A
A
$ echo B
B
$ diff --color <( $(fc -ln -1 -1) ) <( $(fc -ln -2 -2 ) )
1c1
< B
---
> A
Run Code Online (Sandbox Code Playgroud)
fc 标志是:
-n:没有数字。它在列出时抑制命令编号。
-l:列表:命令在标准输出上列出。
指-1
-1
历史记录中的开始和结束位置,在本例中是从最后一个命令到最后一个命令,仅生成最后一个命令。
最后,我们将其包装起来$()
以在子 shell 中执行命令。
显然,输入起来有点麻烦,所以我们可以创建一个别名:
alias dl='diff --color <( $(fc -ln -1 -1) ) <( $(fc -ln -2 -2 ) )'
Run Code Online (Sandbox Code Playgroud)
或者我们可以创建一个函数:
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") )
}
Run Code Online (Sandbox Code Playgroud)
它支持指定要使用的历史行。使用两者后,我发现别名是我更喜欢的版本。
对于 zsh, using 会=(command)
自动创建一个临时文件并替换=(command)
为文件本身的路径。使用命令替换,$(command)
替换为命令的输出。
所以有以下三种选择:
$(...)
<(...)
=(...)
zsh 风格的进程替代,#3,非常有用,可以像这样使用 diff 工具比较两个命令的输出,例如 Beyond Compare:
bcomp =(ulimit -Sa | sort) =(ulimit -Ha | sort)
Run Code Online (Sandbox Code Playgroud)
对于 Beyond Compare,请注意您必须使用bcomp
for 上面(而不是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 - 酒吧作品;这是因为如果 diff 注意到其参数之一是 - ,则会创建一个临时文件,然后将其标准输入复制到临时文件。
参考:https : //unix.stackexchange.com/questions/393349/difference-between-subshells-and-process-substitution
归档时间: |
|
查看次数: |
102740 次 |
最近记录: |