我正在尝试运行以下命令:
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
子句的括号以及find
used (详情见评论和聊天)。
无论如何,可以像这样简化命令:
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 find
POSIX 兼容的功能)。
如果您想坚持使用较旧的 GNU 查找,您可以使用-print0
withxargs -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/null
到grep
命令行是确保 grep 始终打印文件名的技巧,即使find
碰巧找到了单个匹配项。使用 GNU find,另一种方法是传递 option -H
。
如果一个命令如
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 双重转义特殊字符。