如何将两个不同命令的结果合并和管道到单个命令?

Dav*_*ill 45 command-line

我想从两个不同的命令合并(联合)输出,并将它们通过管道传输到单个命令。

一个愚蠢的例子:

我想合并输出的命令:

cat wordlist.txt
ls ~/folder/*
Run Code Online (Sandbox Code Playgroud)

进入:

wc -l
Run Code Online (Sandbox Code Playgroud)

在这个例子中,如果 wordlist.txt 包含 5 行和 3 个文件,我想wc -l返回 8。

$cat wordlist.txt *[magical union thing]* ls ~/folder/* | wc -l
8
Run Code Online (Sandbox Code Playgroud)

我怎么做?

pab*_*mme 69

神奇的联合是一个分号......和花括号:

    { cat wordlist.txt ; ls ~/folder/* ; } | wc -l
Run Code Online (Sandbox Code Playgroud)

花括号只是将命令组合在一起,因此管道符号|会影响组合输出。

您还可以()在命令组周围使用括号,这将在子 shell 中执行命令。这与花括号有一些微妙的区别,例如,请尝试以下操作:

    cd $HOME/Desktop ; (cd $HOME ; pwd) ; pwd
    cd $HOME/Desktop ; { cd $HOME ; pwd ; } ; pwd
Run Code Online (Sandbox Code Playgroud)

您将看到所有环境变量(包括当前工作目录)在退出括号组后都被重置,但在退出大括号组后不会重置。

至于分号,替代方案包括&&||符号,只有在第一个命令成功或不成功时,它们才会有条件地执行第二个命令,例如

    cd $HOME/project && make
    ls $HOME/project || echo "Directory not found."
Run Code Online (Sandbox Code Playgroud)

  • 那行得通!帮助我学习 - 这里的花括号究竟是做什么的?他们还有什么神奇的力量? (2认同)

Lek*_*eyn 9

由于wc接受文件路径作为输入,您还可以使用进程替换:

wc -l <(cat wordlist.txt; ls ~/folder/*)
Run Code Online (Sandbox Code Playgroud)

这大致相当于:

echo wordlist.txt > temp
ls ~/folder/* >> temp
wc -l temp
Run Code Online (Sandbox Code Playgroud)

请注意,ls ~/folder/*如果有的话,也会返回子目录的内容(由于 glob 扩展)。如果您只想列出 的内容~/folder,只需使用ls ~/folder.

  • @DavidOneill 好吧,因为`cat` 接受一个文件参数,你可以使用`cat &lt;(cat wordlist.txt; ls wordlist.txt) | | wc -l` 甚至`cat wordlist.txt &lt;(ls wordlist.txt) | wc -l`。这当然非常丑陋,但它展示了命令行工具的无限可能性。 (3认同)
  • @DavidOneill 正确,我现在已经更正了,谢谢。 (2认同)
  • 你需要 `ls ~/folder/` 以便如果 `~/folder` 是一个符号链接,`ls` 会列出其目标的内容而不是链接本身。顺便说一下,所有的 `ls` 命令都应该跟在 `-1` 之后,这样每行打印一个文件,并且 `wc -l` 是一种有效的文件计数方式。 (2认同)