如何包括管道| 在我的linux中找到-exec命令?


220

这不起作用。可以在查找中完成吗?还是我需要xargs?

find -name 'file_*' -follow -type f -exec zcat {} \| agrep -dEOE 'grep' \;

Answers:


144

将管道符号解释为运行多个进程并将一个进程的输出通过管道传递到另一个进程的输入的指令是外壳程序的职责(/ bin / sh或等效命令)。

在您的示例中,您可以选择使用顶级外壳执行管道,如下所示:

find -name 'file_*' -follow -type f -exec zcat {} \; | agrep -dEOE 'grep'

就效率而言,此结果花费了find的一次调用,zcat的多次调用和agrep的一次调用。

这将导致仅产生一个agrep进程,该进程将处理zcat多次调用产生的所有输出。

如果出于某种原因您想多次调用agrep,则可以执行以下操作:

find . -name 'file_*' -follow -type f \
    -printf "zcat %p | agrep -dEOE 'grep'\n" | sh

这使用管道构造了要执行的命令列表,然后将这些命令发送到新的外壳以实际执行。(省略最后的“ | sh”是调试或执行此类命令行的不错的方法。)

就效率而言,此结果花费了find的一次调用,sh的一次调用,zcat的多次调用和agrep的多次调用。

就命令调用次数而言,最有效的解决方案是Paul Tomblin的建议:

find . -name "file_*" -follow -type f -print0 | xargs -0 zcat | agrep -dEOE 'grep'

...花费了find的一次调用,xargs的一次调用,zcat的几次调用和agrep的一次调用。


1
xargs的另一个优点是,您可以使用-P开关(-P 0)进一步提高现代多核cpu的速度。
flolo

是的,-P swich确实确实是一种通常提高执行速度的好方法。不幸的是,您冒着将并行zcat进程的输出通过管道交错插入agrep的风险,这会影响结果。可以使用以下方法证明这种效果:echo -e“ 1 \ n2” | xargs -P 0 -n 1是| uniq
Rolf W. Rasmussen

@Adam,我已完成您建议的更改。
Paul Tomblin,

您可以为其安装splendid xjobs命令(最初是从Solaris开始的)
sehe 2011年

4
一个更简单,更通用的答案是在stackoverflow.com/a/21825690/42973-exec sh -c "… | … " \;
Eric O Lebigot

277

解决方案很容易:通过sh执行

... -exec sh -c "zcat {} | agrep -dEOE 'grep' " \;

17
OP试图完成的任务可以通过上面的建议来解决,但这实际上是回答所提出的问题的建议。有这样做的理由-exec比仅对find返回的文件进行操作要强大得多,尤其是与test结合使用时。例如:find geda-gaf / -type d -exec bash -c'DIR = {}; [[$(find $ DIR -maxdepth 1 | xargs grep -i spice | wc -l)-ge 5]] && echo $ DIR'\; 将返回搜索路径中的所有目录,其中该目录中所有包含spice的文件中的总行数超过5行
swarfrat 2012年

3
最佳答案。抓紧整个输出(如其他答案所示)与grep每个文件都不相同。提示:您可以使用所需的任何其他shell代替sh,(我使用bash尝试了它,并且运行正常)。
pagliuca

1
确保不要忽略该-c选项。否则,您会收到令人费解的No such file or directory错误消息。
asmaier 2013年

这是一个很好的ps替代品,它利用exec'd shell内部的管道查找:/ usr / bin / find / proc -mindepth 1 -maxdepth 1 -type d -regex'。* / [0-9] +'-打印-exec bash -c“ cat {} / cmdline | tr'\\ 0'''; echo” \;
parity3 2014年

1
使用正则表达式 查找文件并用sed重命名的示例find -type f -name '*.mdds' -exec sh -c "echo {} | sed -e 's/_[0-9]\+//g' | xargs mv {}" \;
Rostfrei 2015年

16
find . -name "file_*" -follow -type f -print0 | xargs -0 zcat | agrep -dEOE 'grep'

出于效率考虑,希望避免使用-print和xargs。也许这确实是我的问题:find无法通过-exec处理管道命令
someguy

这不适用于名称中带有空格的文件。修复,将-print替换为-print0并将-0选项添加到xargs
Adam Rosenfield

2
@someguy-哇?出于效率原因避免使用xargs?调用ZCAT的一个实例,并通过它的多个文件的列表,是远远效率比EXEC-ING它的一个新实例,为每个找到的文件。
Sherm Pendley's

@Adam-我已完成您建议的更改。99%的时间在我的源代码目录中,并且文件中都没有空格,所以我不必理会print0。另一方面,现在我的文档目录中,我还记得print0。
Paul Tomblin,

10

您还可以通过管道传递到while循环,该循环可以对find找到的文件执行多个操作。因此,这里是用于在jar存档中查找包含大量jar文件发行版的文件夹中给定的Java类文件的工具

find /usr/lib/eclipse/plugins -type f -name \*.jar | while read jar; do echo $jar; jar tf $jar | fgrep IObservableList ; done

关键是while循环包含多个引用传入文件名的命令,这些命令用分号分隔,这些命令可以包含管道。因此,在该示例中,我回显匹配文件的名称,然后列出给定类名的存档过滤中的内容。输出如下:

/usr/lib/eclipse/plugins/org.eclipse.core.contenttype.source_3.4.1.R35x_v20090826-0451.jar /usr/lib/eclipse/plugins/org.eclipse.core.databinding.observable_1.2.0.M20090902-0800 .jar org / eclipse / core / databinding / observable / list / IObservableList .class /usr/lib/eclipse/plugins/org.eclipse.search.source_3.5.1.r351_v20090708-0800.jar / usr / lib / eclipse / plugins / org.eclipse.jdt.apt.core.source_3.3.202.R35x_v20091130-2300.jar /usr/lib/eclipse/plugins/org.eclipse.cvs.source_1.0.400.v201002111343.jar / usr / lib / eclipse / plugins / org.eclipse.help.appserver_3.1.400.v20090429_1800.jar

在我的bash shell(xubuntu10.04 / xfce)中,确实使匹配的类名加粗,因为fgrep高亮显示了匹配的字符串;这使得扫描数百个jar文件列表变得非常容易,并且可以轻松查看任何匹配项。

在Windows上,您可以执行以下操作:

for /R %j in (*.jar) do @echo %j & @jar tf %j | findstr IObservableList

请注意,在Windows上,命令分隔符是'&'而不是';' 就像上面的linux find输出一样,“ @”抑制了命令的回显以提供整洁的输出;尽管findstr未将匹配的字符串设为粗体,所以您必须在输出处稍微看一点才能看到匹配的类名。事实证明,Windows的“ for”命令知道许多技巧,例如循环遍历文本文件...

请享用



0

如果您正在寻找一个简单的替代方法,则可以使用循环来完成:

for i in $(find -name 'file_*' -follow -type f);do zcat $i | agrep -dEOE 'grep');done

或者,更一般和易于理解的形式:

for i in $(YOUR_FIND_COMMAND);do YOUR_EXEC_COMMAND_AND_PIPES );done

并在YOUR_EXEC_COMMAND_AND_PIPES中用$ i替换任何{}

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.