将命令输出行作为 Linux 中的另一个命令运行

将命令输出行作为 Linux 中的另一个命令运行

我正在运行这个命令:

find ./ -type f -printf "wc -l \"%p\"\n"

这给出了这个输出:

wc -l "ANLS 457567.pl"
wc -l "ANLS 457567.pl"

现在我想将整行作为另一个命令运行。

我怎样才能实现这个目标?

我知道我可以用来xargs将其输出作为参数传递给另一个命令,但出于好奇,我想知道是否(作为另一个命令运行命令输出行)是可能的。

答案1

虽然您可以将这样的命令通过管道传输到 shell,但它可能会出现一些非常问题,因为任何 glob 和变量以及其他内容都将被扩展。

包含例如星号(*、 glob)或美元符号($、变量和命令扩展)的文件名将导致问题。您需要确保正确引用所有内容,并且在一般情况下,您的文件名本身可以包含引号,因此这并不容易。


但在 的情况下find,它可以自己执行外部命令:

find ./  -type f -exec wc -l {} \;

the{}被当前文件名替换,并且末尾的(带引号的)分号是必需的。

至少某些版本find支持另一种格式,可以一次性给出多个文件名来执行命令,从而节省大量执行:

find ./  -type f -exec wc -l {} \+

答案2

只需将其传递给 shell 的 STDIN:

find ./  -type f -printf "wc -l \"%p\"\n" | sh 

或者如果 shell 支持进程替换,则<()

sh <(find ./  -type f -printf "wc -l \"%p\"\n")

只需find

find ./  -type f -exec wc -l {} +

答案3

有关此案例的实际解决方案,请参阅@ilkkachu 评论。但除此之外,shell 在执行每一行之前都会扩展变量,因此

find ./  -type f -printf "wc -l %p\n" | while read line; do
    $line
done

会工作得很好(除非在文件名中找到特殊字符 - 例如空格)。

请注意$line周围没有引号,我们也没有引用%p。那是因为我们shell 在执行之前将行分割成单词——将单词视为$line命令及其参数,就像您自己编写它们一样。这就是空格不起作用的原因。

通过使用内置的 shell 可以避免这种情况eval真的就像您在 shell 中输入命令一样工作 - 包括引号(现在又回来了):

find ./  -type f -printf "wc -l \"%p\"\n" | while read line; do
    eval $line
done

最后一个应该适用于所有情况 - 但仍然不是一个好的做法。eval应该是最后的手段。我包含这些选项只是为了让您知道它们有效,但通常有更好的方法,-exec例如find.

相关内容