如何在linux find -exec命令中包含管道符 |?
问题的原因是:通过-exec参数在find命令中无法处理管道命令。
解决方法是:使用-print和xargs命令来代替管道命令,但这样效率不高。为了解决文件名中带有空格的问题,需要将-print替换为-print0,并在xargs命令中添加-0选项。
对于避免使用xargs命令的原因,其实通过调用一个zcat实例并传递一个包含多个文件的列表给它,要比为每个找到的文件执行一个新的zcat实例更高效。
根据作者的建议,已经进行了修改。作者在源代码目录中的大部分时间都不会有文件名带有空格,所以不需要使用print0选项。但是在文档目录中,作者会记得使用print0选项。
对于-print0、xargs -0以及带有空格的文件名,如果能做一些简单的解释,那就更好了。
如何在Linux的find -exec命令中包含管道符“|”?
某些情况下了一个解决方法:通过sh执行
... -exec sh -c "zcat {} | agrep -dEOE 'grep' " \;
OP试图实现的目标可以通过上面的建议来实现,但这是唯一回答了所问问题的方法。有很多原因可以选择这种方式- exec比仅仅操作find返回的文件更强大,特别是与test结合使用。例如:
find geda-gaf/ -type d -exec bash -c 'DIR={}; [[ $(find $DIR -maxdepth 1 |xargs grep -i spice |wc -l) -ge 5 ]] && echo $DIR' \;
将返回在搜索路径中包含单词spice的所有目录,这些目录中包含的文件的总行数超过5行。
最佳答案。在其他答案建议的对整个输出进行grep之前进行grep并不相同。提示:您可以使用任何其他您想要的shell(我尝试过bash,它可以正常运行)。
请务必不要忽略-c
选项。否则,您将收到一个令人困惑的No such file or directory
错误消息。
这是一个很好的使用find和在exec的shell中使用管道的替代ps命令的示例:
/usr/bin/find /proc -mindepth 1 -maxdepth 1 -type d -regex '.*/[0-9]+' -print -exec bash -c "cat {}/cmdline | tr '\\0' ' ' ; echo" \;
通过正则表达式查找文件并使用sed进行重命名的示例:
find -type f -name '*.mdds' -exec sh -c "echo {} | sed -e 's/_[0-9]\+//g' | xargs mv {}" \;
在AIX上,引号内的{}不会被替换为文件名,因此这种解决方法无效。
尝试在外部范围的括号和单引号上加上双引号-type f -exec sh -c 'echo "{}"' | grep something\;
这不能保证{}
扩展到适合shell的引号。更好的方法是将{}
作为参数传递,例如-exec sh -c 'zcat "$1" | agrep -dEoE "grep" ' _ {} \;
(其中_
只是一个用于设置在执行的shell中的$0
的虚拟参数)。
在Linux的find命令中,如果想要在-exec命令中包含管道符“|”,需要注意shell对管道符的解析。在执行find命令时,shell会解析管道符并将其作为一个指令,用于运行多个进程并将一个进程的输出作为另一个进程的输入。
解决这个问题的方法有几种,具体取决于需求和效率要求。
第一种方法是使用顶层shell来执行管道操作。例如:
find -name 'file_*' -follow -type f -exec zcat {} \; | agrep -dEOE 'grep'
这种方法的效率相对较低,因为它需要多次调用zcat和agrep进程。
第二种方法是构建一个命令列表,并将其发送给一个新的shell来执行。例如:
find . -name 'file_*' -follow -type f \ -printf "zcat %p | agrep -dEOE 'grep'\n" | sh
这种方法的效率相对较高,因为它只需要一次调用find和sh进程,但需要多次调用zcat和agrep进程。
第三种方法是使用xargs命令来处理管道操作。例如:
find . -name "file_*" -follow -type f -print0 | xargs -0 zcat | agrep -dEOE 'grep'
这种方法的效率最高,因为它只需要一次调用find和xargs进程,少量调用zcat和一次调用agrep进程。
需要注意的是,使用xargs命令时,如果使用了-P参数来并行处理任务,可能会导致并行的zcat进程的输出与agrep进程的输入交错,从而影响结果。
除了上述方法,还可以使用-exec参数中的sh命令来执行管道操作,例如:
-exec sh -c "… | … " \;
但这种方法虽然简单,但不符合问题的要求。
总结起来,根据不同的需求和效率要求,可以选择合适的方法来在Linux的find命令中包含管道符“|”。