如何在linux find-exec命令中包含管道?

如何在linux find-exec命令中包含管道?,linux,command-line,Linux,Command Line,这不管用。这可以在find中完成吗?或者我需要xargs吗 find -name 'file_*' -follow -type f -exec zcat {} \| agrep -dEOE 'grep' \; 解决方案很简单:通过sh执行 ... -exec sh -c "zcat {} | agrep -dEOE 'grep' " \; shell(/bin/sh或等效程序)负责将管道符号解释为运行多个进程的指令,并将一个进程的输出管道化为另一个进程的输入 在您的示例中,您可以选择使用顶级

这不管用。这可以在find中完成吗?或者我需要xargs吗

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

解决方案很简单:通过sh执行

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

shell(/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
这将使用管道构造一个要执行的命令列表,然后将这些命令发送到实际要执行的新shell。(省略最后一个“| sh”是调试或执行类似命令行的干运行的好方法。)

就效率而言,这个结果需要一次find调用、一次sh调用、多次zcat调用和多次agrep调用

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

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

。。。这需要一次find调用、一次xargs调用、几次zcat调用和一次agrep调用。

您还可以通过管道连接到
while
循环,该循环可以对
find
定位的文件执行多个操作。因此,这里有一个用于查找文件夹中给定java类文件的
jar
归档,文件夹中有大量
jar
文件发行版

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.v20100211343.jar /usr/lib/eclipse/plugins/org.eclipse.help.appserver_3.1.400.v20090429_1800.jar

在我的bashshell(xubuntu10.04/xfce)中,当
fgrep
突出显示匹配的字符串时,它确实使匹配的类名变为粗体;这样就可以很容易地扫描搜索到的数百个
jar
文件列表,并轻松查看任何匹配项

在windows上,您可以对以下各项执行相同的操作:

for /R %j in (*.jar) do @echo %j & @jar tf %j | findstr IObservableList
请注意,在windows上,命令分隔符为“&”not“;”“@”抑制命令的回音,以提供整洁的输出,就像上面的LinuxFind输出一样;虽然
findstr
未启用,但将匹配的字符串设为粗体,因此您必须仔细查看输出以查看匹配的类名。事实证明,windows“for”命令知道很多技巧,比如循环浏览文本文件


享受

如果您正在寻找一个简单的替代方案,可以使用循环:

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

并在您的_EXEC_命令_和_PIPES中将任何{}替换为$i

我发现运行字符串shell命令(sh-c)效果最好,例如:

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

为了提高效率,希望避免打印和xargs。也许这真的是我的问题:find无法通过-exece处理管道命令这不适用于名称中带有空格的文件;要修复此问题,请将-print替换为-print0,并将-0选项添加到xargs@someguy-什么?出于效率原因而避免XARG?调用zcat的一个实例,并向其传递多个文件的列表,比为每个找到的文件执行一个新的zcat实例要有效得多。@Adam-我已经做了您建议的更改。99%的情况下,当我进行查找时,它都在我的源代码目录中,那里的文件都没有空格,所以我不必为print0操心。另一方面,现在我的文档目录中,我记得print0。xargs的另一个优点是,使用-P开关(-P 0),您可以使用现代多核cpu进一步提高它的速度。是的,-P开关确实是一种提高执行速度的好方法。不幸的是,并行zcat进程的输出可能会被管道传输到agrep Interleave,这将影响结果。可以使用:echo-e“1\n2”| xargs-P 0-n 1 yes|来演示此效果uniq@Adam,我已经做了您建议的更改。对于此更改,您可以安装辉煌的xjobs命令(最初来自Solaris)。一个更简单、更一般的答案是:
-exec sh-c“。OP试图实现的目标可以通过上面的建议来实现,但这就是实际回答问题的方法。这样做是有原因的——exec比只操作find返回的文件要强大得多,尤其是与test结合使用时。例如:find geda gaf/-type d-exec bash-c'DIR={};[[$(查找$DIR-maxdepth 1 | xargs grep-i spice | wc-l)-ge 5]&&echo$DIR'\;将返回搜索路径中的所有目录,其中包含该目录中包含单词“最佳答案”的所有文件的总行数超过5行。对整个输出进行grep(如其他答案所示)与对每个文件进行grep不同。提示:代替sh,您可以使用您想要的任何其他shell(我用bash试过了,它运行正常)。请确保不要忽略
-c
选项。否则,您将得到一个令人费解的
文件或目录
find -name 'file_*' -follow -type f -exec bash -c "zcat \"{}\" | agrep -dEOE 'grep'" \;