题
我正在尝试构建一个 find 命令来使用两个不同的可执行文件处理目录中的一堆文件。很遗憾, -exec
查找时不允许使用管道,甚至不允许使用 \|
因为 shell 首先解释该字符。
这是我具体想要做的事情(这不起作用,因为管道结束了 find 命令):
find /path/to/jpgs -type f -exec jhead -v {} | grep 123 \; -print
解决方案
尝试这个
find /path/to/jpgs -type f -exec sh -c 'jhead -v {} | grep 123' \; -print
或者,您可以尝试将 exec 语句嵌入 sh 脚本中,然后执行以下操作:
find -exec some_script {} \;
其他提示
稍微不同的方法是使用 xargs:
find /path/to/jpgs -type f -print0 | xargs -0 jhead -v | grep 123
我总是发现它更容易理解和适应(-print0 和 -0 参数对于处理包含空格的文件名是必要的)
这 可能 (未经测试)比使用 -exec 更有效,因为它将文件列表通过管道传输到 xargs,并且 xargs 确保 jhead 命令行不会太长。
和 -exec
您只能运行带有某些参数的单个可执行文件,而不能运行任意 shell 命令。为了避免这个问题,你可以使用 sh -c '<shell command>'
.
请注意,使用 -exec
效率相当低。对于找到的每个文件,都必须再次执行该命令。如果能避免这种情况,效率会更高。(例如,通过移动 grep
之外的 -exec
或通过管道传输结果 find
到 xargs
正如建议的 帕尔明.)
使用 find
对于此类任务,命令可能不是最好的选择。我经常使用以下命令来查找包含所请求信息的文件:
for i in dist/*.jar; do echo ">> $i"; jar -tf "$i" | grep BeanException; done
由于这会输出一个列表,您不会:
find /path/to/jpgs -type f -exec jhead -v {} \; | grep 123
或者
find /path/to/jpgs -type f -print -exec jhead -v {} \; | grep 123
将 grep 放在 find -exec 的结果上。
还有另一种方法可以做到这一点,但它也很贫民窟。
使用 shell 选项 extquote 您可以执行类似的操作,以便找到 exec 内容,然后通过管道将其传输到 sh。
root@ifrit findtest # find -type f -exec echo ls $"|" cat \;|sh
filename
root@ifrit findtest # find -type f -exec echo ls $"|" cat $"|" xargs cat\;|sh
h
我只是想我应该补充一点,因为至少从我想象的方式来看,它更接近OP最初在exec中使用管道的问题。