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


35

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

一个愚蠢的例子:

我想合并输出的命令:

cat wordlist.txt
ls ~/folder/*

变成:

wc -l

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

$cat wordlist.txt *[magical union thing]* ls ~/folder/* | wc -l
8

我怎么做?

Answers:


56

神奇的结合是分号...和花括号:

    { cat wordlist.txt ; ls ~/folder/* ; } | wc -l

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

您还可以()在命令组周围使用括号,这将在子shell中执行命令。大括号之间有一些细微的差异,例如,尝试以下操作:

    cd $HOME/Desktop ; (cd $HOME ; pwd) ; pwd
    cd $HOME/Desktop ; { cd $HOME ; pwd ; } ; pwd

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

对于分号,备选方案包括&&||符号,它们将分别在第一个命令成功或失败的情况下有条件地执行第二个命令,例如

    cd $HOME/project && make
    ls $HOME/project || echo "Directory not found."

1
那行得通!帮助我学习-这里的花括号到底在做什么?他们还有什么其他魔力?
David Oneill'5

@DavidOneill { list; }复合命令。From bash(1)list在当前的shell环境中简单地执行。列表必须以换行符或分号终止。[..]返回状态是列表的退出状态。
Lekensteyn'5

我已经为答案添加了更多信息。使用bash进行shell脚本编写的权威指南是bash联机帮助页,可man bash从命令行键入并浏览它。
pablomme 2012年

应该; 如果文件wordlist.txt不存在,这些命令不是&&吗?
Rinzwind

如果wordlist.txt不存在,则来自的错误cat将出现在标准错误上,但不会出现在标准输出上,因此wc -l不会从中计算任何行。~/folder不存在的情况相同。可以2> /dev/null在每个命令及其分号之间添加一个以防止标准错误产生噪音,但是除了难看之外,错误消息对于计数行无害。
pablomme 2012年

8

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

wc -l <(cat wordlist.txt; ls ~/folder/*)

这大致相当于:

echo wordlist.txt > temp
ls ~/folder/* >> temp
wc -l temp

注意,ls ~/folder/*如果有的话,它还会返回子目录的内容(由于全局扩展)。如果只想列出的内容~/folder,请使用ls ~/folder


wc -l只是一个虚构的示例,我实际上是将其传递到没有此选项的更复杂的示例中。
David Oneill'5

2
@DavidOneill好吧,由于cat接受文件参数,因此可以使用cat <(cat wordlist.txt; ls wordlist.txt) | wc -l甚至cat wordlist.txt <(ls wordlist.txt) | wc -l。这当然很丑陋,但是它展示了命令行工具的无限可能性。
Lekensteyn'5

1
@DavidOneill正确,谢谢,我现在已经更正了。
Lekensteyn'5

1
您希望ls ~/folder/if ~/folder符号链接ls列出其目标的内容,而不是链接本身。顺便说一句,所有ls命令都应跟在后面,-1以便每行打印一个文件,这wc -l是计数文件的有效方法。
pablomme 2012年

@pablomme您对symlink事情的看法是正确的,但是-1它的隐含含义是输出不是终端而是管道。
Lekensteyn'5

2

我在问自己同样的问题,最后写了一个简短的脚本。

magicalUnionThing(我称之为append):

#!/bin/sh
cat /dev/stdin
$*

使该脚本可执行

chmod +x ./magicalUnionThing

你现在做

cat wordlist.txt |./magicalUnionThing ls ~/folder/* | wc -l

它能做什么:

  • 将标准输入发送到标准输出
  • 执行参数。$*以字符串形式返回所有参数。默认情况下,该命令的输出将转到脚本标准输出。

因此,magicalUnionThing的标准输出将是作为参数传递的命令的标准输入+标准输出。

当然,还有其他更简单的方法。
在某些情况下,此替代方法可能有用。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.