我正在尝试构建一个 find 命令来使用两个不同的可执行文件处理目录中的一堆文件。不幸的是,-exec
在 find 上不允许使用管道,甚至\|
因为 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
效率非常低。对于找到的每个文件,必须再次执行该命令。如果你能避免这种情况会更有效率。(例如,按照 Palmin 的建议,通过移动外部或管道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 中使用管道的原始问题。