查找:-exec 缺少参数

查找:-exec 缺少参数

我正在尝试运行以下命令:

find a/folder b/folder -name *.c -o -name *.h -exec grep -I foobar '{}' +

这是返回一个错误:

find: missing argument to -exec

我看不出这个命令有什么问题,因为它似乎与手册页相匹配:

-执行命令{} +

-exec 选项的这个变体在选定的文件上运行指定的命令,但命令行是通过在末尾附加每个选定的文件名来构建的;该命令的调用总数将远小于匹配文件的数量。命令行的构建方式与 xargs 构建其命令行的方式大致相同。命令中只允许出现一个“{}”实例。该命令在起始目录中执行。

我也尝试过:

find a/folder b/folder -name *.c -o -name *.h -exec grep -I foobar {} +
find a/folder b/folder -name *.c -o -name *.h -exec 'grep -I foobar' {} +
find a/folder b/folder -name *.c -o -name *.h -exec 'grep -I foobar' '{}' +
find a/folder b/folder -name "*.c" -o -name "*.h" -exec grep -I foobar '{}' +
find a/folder b/folder \( -name *.c -o -name *.h \) -exec grep -I foobar '{}' +
find a/folder b/folder -name *.c -o -name *.h -exec grep -I foobar '{}' \+

答案1

您的尝试存在几个问题,包括使用反引号代替引号(在问题的后续编辑中删除)、在需要的地方缺少引号、在无用的地方额外引号、缺少分组子句的括号-o以及find使用的不同实现(详情请参阅评论和聊天)。

无论如何,命令可以像这样简化:

find a/folder b/folder -name "*.[ch]" -exec grep -I foobar {} +

或者,如果您使用古老的 GNU find 版本,这应该始终有效:

find a/folder b/folder -name "*.[ch]" -exec grep -I foobar {} \;

答案2

“missing argument to -exec”通常意味着 - 的参数exec缺少其终止符。终止符必须是仅包含字符的参数;(需要在 shell 命令中引用,因此通常写为\;';'),或者是两个包含{}和 的连续参数+

斯蒂芬·查泽拉斯 (Stephane Chazelas) 已确定您正在使用旧版本的 GNU find,它不支持-exec … {} +, 仅-exec {} \;.尽管 GNU 是 的较晚采用者-exec … {} +,但我确实建议您使用不太古董的工具套件(例如西格文,其中包括 git 和更多内容,或者GNUwin32,它缺少 git,但没有 Cygwin 提供的坏员工试图使用 linux-but-we-impose-windows 氛围)。该功能是在 9 年前的 4.2.12 版本中添加的(这是最后一个确定的使 GNU findPOSIX 兼容的功能)。

如果您想坚持使用较旧的 GNU 查找,可以使用-print0withxargs -0来获得类似的功能:分组命令执行、支持任意文件名。

find a/folder b/folder -name '*.c' -o -name '*.h' -print0 | xargs -0 grep -I foobar /dev/null

始终在命令行上引用通配符find。否则,如果您碰巧从包含文件的目录运行此命令.c,则未加引号的内容将扩展到当前目录中的文件*.c列表。.c

添加/dev/nullgrep命令行是确保 grep 始终打印文件名的技巧,即使find碰巧找到单个匹配项也是如此。对于 GNU find,另一种方法是传递选项-H

答案3

如果一个命令如

find a/folder b/folder -name "*.c" -o -name "*.h" -exec grep -I foobar {} +

返回错误

find: missing argument to -exec

可能的原因是 GNU 太旧find,不支持语法-exec mycommand {} +。在这种情况下,低性能替换是运行-exec mycommand {} \;,它将mycommand为每个找到的目标运行一次,而不是收集多个目标并mycommand仅运行一次。

然而,GNUfind不支持例如

find . -type f -and -name "*.ttf" -exec cp {} ~/.fonts +

因为 GNUfind仅支持文字组合{} +而不是更通用的{} additional parameters +。请注意,大括号和字符之间不能有任何内容+。如果你尝试这样做,你会得到同样的错误:

find: missing argument to -exec

解决方法是使用{} additional parameters \;确实有效但会为每个找到的目标执行一次命令的语法。如果您需要 GNU 的更高性能,find则必须编写一个包装脚本,该脚本可以将其他参数附加到给定的参数中。就像是

#!/bin/bash
exec mycommand "$@" additional parameters

应该足够好了。或者,如果您不想创建临时文件,可以使用单行命令更改参数顺序,如下所示:

find . -type f -and -name "*.ttf" -exec bash -c 'mycommand "$@" extra arguments' {} +

这将执行mycommand {list of ttf files} extra arguments.请注意,您可能需要在标志后面对 bash 的特殊字符进行双重转义-c

答案4

过去我曾对 exec 语法感到头痛。现在大多数时候我更喜欢更好的 bash 语法:

for f in `find a/folder b/folder -name "*.[ch]"`; do grep -I foobar $f; done

当您想要将文件视为一个组时,它有一些限制,因为每个文件都是串行评估的,但您可以将输出通过管道传输到其他地方就可以了

相关内容