我如何包含管道 | 在我的 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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 16:44:46  来源:igfitidea点击:

How do I include a pipe | in my linux find -exec command?

linuxcommand-line

提问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 whileloop that can do multiple actions on the file which findlocates. So here is one for looking in jararchives for a given java class file in folder with a large distro of jarfiles

您还可以通过管道连接到一个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 whileloop 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 fgrephighlights the matched string; this makes it really easy to scan down the list of hundreds of jarfiles 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 findstris 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'" \;