查找:缺少 -exec 的参数

Big*_*uge 42 find

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

find a/folder b/folder -name *.c -o -name *.h -exec grep -I foobar '{}' +
Run Code Online (Sandbox Code Playgroud)

这是返回错误:

find: missing argument to -exec
Run Code Online (Sandbox Code Playgroud)

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

-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 '{}' \+
Run Code Online (Sandbox Code Playgroud)

jll*_*gre 34

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

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

find a/folder b/folder -name "*.[ch]" -exec grep -I foobar {} +
Run Code Online (Sandbox Code Playgroud)

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

find a/folder b/folder -name "*.[ch]" -exec grep -I foobar {} \;
Run Code Online (Sandbox Code Playgroud)


Gil*_*il' 20

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

斯特凡Chazelas已确定您所使用的GNU发现不支持的旧版本-exec … {} +而已,-exec {} \;。尽管 GNU 是 的较晚采用者-exec … {} +,但我确实建议您获得一个不那么陈旧的工具套件(例如Cygwin,它包括 git 和更多的东西,或者GNUwin32,它缺少 git 但没有坏员工的尝试Cygwin 提供的 -to-use-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
Run Code Online (Sandbox Code Playgroud)

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

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


Mik*_*nen 7

如果一个命令如

find a/folder b/folder -name "*.c" -o -name "*.h" -exec grep -I foobar {} +
Run Code Online (Sandbox Code Playgroud)

返回错误

find: missing argument to -exec
Run Code Online (Sandbox Code Playgroud)

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

但是,GNUfind不支持例如

find . -type f -and -name "*.ttf" -exec cp {} ~/.fonts +
Run Code Online (Sandbox Code Playgroud)

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

find: missing argument to -exec
Run Code Online (Sandbox Code Playgroud)

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

find a/folder b/folder -name "*.c" -o -name "*.h" -exec grep -I foobar {} +
Run Code Online (Sandbox Code Playgroud)

应该够好了。或者,如果您不想创建临时文件,您可以使用 one-liner 更改参数的顺序,如下所示:

find . -type f -and -name "*.ttf" -exec bash -c 'mycommand "$@" extra arguments' {} +
Run Code Online (Sandbox Code Playgroud)

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

  • +1 最后,有人回答了为什么附加参数不起作用!这似乎是 POSIX 定义中的一个缺陷。 (4认同)
  • 如果你有 GNU `find`,你可能已经有 GNU `cp`。在这种情况下,您可以 `find ... -exec cp --target-directory ~/.fonts {} +` 将 `{}` 保留在执行字符串的末尾。 (3认同)