【发布时间】:2010-09-23 08:23:04
【问题描述】:
这不起作用。这可以在find中完成吗?还是我需要 xargs?
find -name 'file_*' -follow -type f -exec zcat {} \| agrep -dEOE 'grep' \;
【问题讨论】:
标签: linux command-line
这不起作用。这可以在find中完成吗?还是我需要 xargs?
find -name 'file_*' -follow -type f -exec zcat {} \| agrep -dEOE 'grep' \;
【问题讨论】:
标签: linux command-line
如果您正在寻找一个简单的替代方案,可以使用循环来完成:
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
【讨论】:
我发现运行字符串 shell 命令 (sh -c) 效果最好,例如:
find -name 'file_*' -follow -type f -exec bash -c "zcat \"{}\" | agrep -dEOE 'grep'" \;
【讨论】:
您还可以通过管道连接到while 循环,该循环可以对find 定位的文件执行多项操作。所以这里有一个用于在jar 档案中查找给定 java 类文件的文件夹,其中包含 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.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'命令知道很多技巧,比如循环遍历文本文件......
享受
【讨论】:
将管道符号解释为运行多个进程并将一个进程的输出通过管道传输到另一个进程的输入的指令的工作是 shell(/bin/sh 或等效项)的职责。
在您的示例中,您可以选择使用顶级 shell 来执行管道,如下所示:
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。
【讨论】:
-exec sh -c "… | … " \;。
解决方法很简单:通过 sh 执行
... -exec sh -c "zcat {} | agrep -dEOE 'grep' " \;
【讨论】:
-c 选项。否则你会得到一个令人费解的No such file or directory 错误信息。
find -type f -name '*.mdds' -exec sh -c "echo {} | sed -e 's/_[0-9]\+//g' | xargs mv {}" \; 查找文件并使用 sed 重命名文件的示例
find . -name "file_*" -follow -type f -print0 | xargs -0 zcat | agrep -dEOE 'grep'
【讨论】: