我如何包含管道 | 在我的 linux find -exec 命令中?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/307015/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I include a pipe | in my linux find -exec command?
提问by someguy
This isn't working. Can this be done in find? Or do I need to xargs?
这不起作用。这可以在查找中完成吗?还是我需要xargs?
find -name 'file_*' -follow -type f -exec zcat {} \| agrep -dEOE 'grep' \;
采纳答案by Rolf W. Rasmussen
The job of interpreting the pipe symbol as an instruction to run multiple processes and pipe the output of one process into the input of another process is the responsibility of the shell (/bin/sh or equivalent).
将管道符号解释为运行多个进程的指令并将一个进程的输出通过管道传送到另一个进程的输入的工作是 shell(/bin/sh 或等效项)的责任。
In your example you can either choose to use your top level shell to perform the piping like so:
在您的示例中,您可以选择使用顶级外壳来执行管道,如下所示:
find -name 'file_*' -follow -type f -exec zcat {} \; | agrep -dEOE 'grep'
In terms of efficiency this results costs one invocation of find, numerous invocations of zcat, and one invocation of agrep.
就效率而言,此结果花费了一次 find 调用、多次 zcat 调用和一次 agrep 调用。
This would result in only a single agrep process being spawned which would process all the output produced by numerous invocations of zcat.
这将导致只产生一个 agrep 进程,该进程将处理由多次调用 zcat 产生的所有输出。
If you for some reason would like to invoke agrep multiple times, you can do:
如果您出于某种原因想要多次调用 agrep,您可以执行以下操作:
find . -name 'file_*' -follow -type f \
-printf "zcat %p | agrep -dEOE 'grep'\n" | sh
This constructs a list of commands using pipes to execute, then sends these to a new shell to actually be executed. (Omitting the final "| sh" is a nice way to debug or perform dry runs of command lines like this.)
这构建了一个使用管道执行的命令列表,然后将它们发送到一个新的 shell 以实际执行。(省略最后的“| sh”是调试或执行像这样的命令行试运行的好方法。)
In terms of efficiency this results costs one invocation of find, one invocation of sh, numerous invocations of zcat and numerous invocations of agrep.
就效率而言,此结果花费了一次 find 调用、一次 sh 调用、多次 zcat 调用和多次 agrep 调用。
The most efficient solution in terms of number of command invocations is the suggestion from Paul Tomblin:
就命令调用次数而言,最有效的解决方案是 Paul Tomblin 的建议:
find . -name "file_*" -follow -type f -print0 | xargs -0 zcat | agrep -dEOE 'grep'
... which costs one invocation of find, one invocation of xargs, a few invocations of zcat and one invocation of agrep.
... 这花费了一次 find 调用、一次 xargs 调用、几次 zcat 调用和一次 agrep 调用。
回答by Paul Tomblin
find . -name "file_*" -follow -type f -print0 | xargs -0 zcat | agrep -dEOE 'grep'
回答by flolo
the solution is easy: execute via sh
解决方案很简单:通过 sh 执行
... -exec sh -c "zcat {} | agrep -dEOE 'grep' " \;
回答by simbo1905
You can also pipe to a while
loop that can do multiple actions on the file which find
locates. So here is one for looking in jar
archives for a given java class file in folder with a large distro of jar
files
您还可以通过管道连接到一个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
the key point being that the while
loop contains multiple commands referencing the passed in file name separated by semicolon and these commands can include pipes. So in that example I echo the name of the matching file then list what is in the archive filtering for a given class name. The output looks like:
关键是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
/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
in my bash shell (xubuntu10.04/xfce) it really does make the matched classname bold as the fgrep
highlights the matched string; this makes it really easy to scan down the list of hundreds of jar
files that were searched and easily see any matches.
在我的 bash shell (xubuntu10.04/xfce) 中,它确实使匹配的类名加粗,因为fgrep
突出显示了匹配的字符串;这使得向下扫描数百个jar
搜索过的文件列表并轻松查看任何匹配项变得非常容易。
on windows you can do the same thing with:
在 Windows 上你可以做同样的事情:
for /R %j in (*.jar) do @echo %j & @jar tf %j | findstr IObservableList
note that in that on windows the command separator is '&' not ';' and that the '@' suppresses the echo of the command to give a tidy output just like the linux find output above; although findstr
is not make the matched string bold so you have to look a bit closer at the output to see the matched class name. It turns out that the windows 'for' command knows quite a few tricks such as looping through text files...
请注意,在 Windows 上,命令分隔符是 '&' 不是 ';' 并且“@”抑制命令的回声以提供整洁的输出,就像上面的 linux find 输出一样;虽然findstr
没有使匹配的字符串加粗,因此您必须更仔细地查看输出才能看到匹配的类名。事实证明,windows 的“for”命令知道很多技巧,例如遍历文本文件......
enjoy
请享用
回答by Louis Gagnon
If you are looking for a simple alternative, this can be done using a loop:
如果您正在寻找一个简单的替代方案,可以使用循环来完成:
for i in $(find -name 'file_*' -follow -type f);do zcat $i | agrep -dEOE 'grep');done
or, more general and easy to understand form:
或者,更一般且易于理解的形式:
for i in $(YOUR_FIND_COMMAND);do YOUR_EXEC_COMMAND_AND_PIPES );done
and replace any {} by $i in YOUR_EXEC_COMMAND_AND_PIPES
并将 YOUR_EXEC_COMMAND_AND_PIPES 中的任何 {} 替换为 $i
回答by Andrew Khoury
I found that running a string shell command (sh -c) works best, for example:
我发现运行字符串 shell 命令 (sh -c) 效果最好,例如:
find -name 'file_*' -follow -type f -exec bash -c "zcat \"{}\" | agrep -dEOE 'grep'" \;