鱼壳

鱼壳

我曾想过,比较两个相似目录内容的最简单方法是这样的

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)会替换为输出该命令。

因此,有三个选择:

  1. 命令替换:$(...)
  2. 流程替代:<(...)
  3. 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 注意到它的一个参数是 -,它会创建一个临时文件,然后将其标准输入复制到临时文件。

参考:https://unix.stackexchange.com/questions/393349/difference-between-subshel​​ls-and-process-substitution

答案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") )
}

它支持指定要使用的历史记录行。使用过两者后,我发现别名是我喜欢的版本。

相关内容