如何在我的 linux find -exec 命令中包含管道 |?
- 2024-10-31 08:38:00
- admin 原创
- 47
问题描述:
这不起作用。可以在 find 中完成吗?还是我需要 xargs?
find -name 'file_*' -follow -type f -exec zcat {} | agrep -dEOE 'grep' ;
解决方案 1:
解决方案很简单:通过 sh 执行
... -exec sh -c "zcat {} | agrep -dEOE 'grep' " ;
解决方案 2:
将管道符号解释为运行多个进程的指令并将一个进程的输出通过管道传输到另一个进程的输入中,这是 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 \n -printf "zcat %p | agrep -dEOE 'grep'
" | 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。
解决方案 3:
find . -name "file_*" -follow -type f -print0 | xargs -0 zcat | agrep -dEOE 'grep'
解决方案 4:
您还可以通过管道连接到一个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”命令知道很多技巧,例如循环遍历文本文件...
享受
解决方案 5:
如果您正在寻找一个简单的替代方法,可以使用循环来完成:
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
解决方案 6:
我发现运行字符串 shell 命令(sh -c)效果最好,例如:
find -name 'file_*' -follow -type f -exec bash -c "zcat \"{}\" | agrep -dEOE 'grep'" ;
解决方案 7:
您应该执行以下操作:
find -name 'file_*' -follow -type f -exec sh -c 'zcat "$1" | agrep -dEOE "grep"' sh {} ;
我尝试了几个这样的答案,但对我来说都不起作用。如果您的文件名包含特殊字符,@flolo 的答案将无法正常工作。根据这个答案:
该
find
命令直接执行命令。该命令(包括文件名参数)不会被 shell 或任何其他可能修改文件名的程序处理。这非常安全。
{}
如果将其放在sh 命令字符串内,则会失去安全性。
@Rolf W. Rasmussen 的回答存在一个潜在问题。是的,它可以处理特殊字符(据我所知),但如果find
输出太长,您将无法执行xargs -0 ...
:内核设置了命令行字符限制,有时您的 shell 也会设置。巧合的是,每次我想从管道传输命令时find
,我都会遇到这个限制。
但是,他们确实提出了有关性能限制的一个有效观点。我不确定如何克服这个问题,尽管就我个人而言,我从未遇到过我的示例太慢的情况。
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理必备:盘点2024年13款好用的项目管理软件