Cygwin 查找返回“缺少 `-exec' 参数”

Cygwin 查找返回“缺少 `-exec' 参数”

我有一个备份脚本,可以删除超过 x 天的备份。

在 Linux 机器上,此方法运行良好:

find /backups/dummy-prod-db -name "*_D_dummy-prod-db*" -type f -mtime +7 -exec rm -v {} \;

但是如果我在装有 Cygwin 的 Windows 机器上运行这个程序:

c:\cygwin64\bin\find.exe "C:\\backups\\dummy-prod-db\\" -name "*_D_dummy-prod-db*" -type f -mtime +7 -exec rm -v {} \;

它返回

/usr/bin/find: missing argument to `-exec'

我该如何修复它?

编辑:

我在 Windows 上使用 CMD shell。

答案1

作为你已经发现了,解决方法是使用;而不是\;。在我的回答中,我将尝试解释这背后的机制。

首先,了解为什么\;在 Linux 上需要 是件好事。这并不明显,但find在 Linux 上, 之后的某个地方需要;(或+) 作为参数-exec,而不是\;;请参阅来自 The Open Group 的规范,它表示-exec utility_name [argument ...] ;。反斜杠是为 shell 准备的。问题是;是 shell 所特有的,它是一个命令终止符。如果您使用;,shell 会将其解释为这样,find根本看不到它。要告诉 shell;不应特殊处理,我们可以使用反斜杠 ( \;) 对其进行转义,也可以将其括起来 (";"';')。shell 将解释并删除反斜杠或引号,并将find看到;它所期望的唯一内容。

您使用的路径c:\cygwin64\bin\find.exe让我相信您不是在 Cygwin 中的 Bash(或类似的 shell)中工作,而是在 中工作cmd.execmd.exe ;不是特殊的,因此无需对其进行转义。此外,\不是转义字符(^是)。\;您使用的 got tofind.exe字面上是\;。该工具未找到;(也没有+)它所期望的 ,因此出现错误。Sole;到达find.exeas ;,这就是该工具所期望的。

据我所知";"cmd.exe最终应该会变成find.exe这样,因为;.";"在 Linux 上也能正常工作,所以我们可以";"在这个问题的上下文中称之为“通用语法”。注意不是通用的,单引号在*';'中不是特殊的。cmd.exe


* 情况稍微复杂一些。

在 Linux 中,可执行文件像 一样find将其参数作为数组获取(在您的情况下:find/backups/dummy-prod-db-name*_D_dummy-prod-db*-typef-mtime+7-exec,,) 。 shell 处理单词拆分和通配符(rm虽然在您的情况下没有未加引号的通配符),它会删除引号、反斜杠。-v{};

在 Windows 中,可执行文件(如)find.exe将其参数作为单个细绳据我所知,在 Windows 系统调用 之前main(),它会_setargv()调用 将命令行解析为标准 Cargcargv[]传递给main()程序函数的参数。程序可以提供自己的_setargv()。这意味着对引号和通配符(如 )的解释*以及拆分为单词(单独的参数)实际上是每个可执行文件的工作,而不是cmd.exe。可执行文件可能使用一些标准_setargv(),那么它几乎就像cmd.exe完成了工作,这种情况类似于 Linux 中的情况;或者它可能提供自己的_setargv()

我写作的地方

";"cmd.exe最终应该find.exe达到;

“最终” 表示“之后_setargv()”。_setargv()引号与命令字符串的其余部分一起出现;如果find.exe提供了自定义的_setargv(),它可以以作者希望的任何方式解释这些引号。

我写道

单引号不是特殊符号cmd.exe

我的意思其实是“不特别适用于常用的_setargv()”。如果find.exe提供了一个自定义的_setargv(),它可以以作者想要的任何方式解释单引号,例如像 Bash 中的单引号一样。我不知道,或许find.exe确实像这样解释单引号。

一般来说,“某事在…中起作用(或不起作用)cmd.exe”包括cmd.exe 一些标准_setargv()

相比之下:在 Windows 中(FIND本机FIND不是*nix 的一个移植版本find)有其独特的语法,因为它对所获取字符串的解释与任何标准都不同_setargv()。您可以在此处找到更多信息:Tcler 的 Wiki / 执行引号问题(请注意,文章的某些部分是在 Tcl 的背景下进行的,与我们的问题无关,但相关片段仍然FIND具有教育意义)。

答案2

我在这里找到了答案:

https://stackoverflow.com/a/32377808/1215291

它说末尾的反斜杠应该被删除。我修改了这一点:

... -exec rm -v {} \;

对此:

... -exec rm -v {} ;

并且它起作用了,但我不明白为什么。

如果有人能解释一下我将不胜感激。

相关内容