Forfiles /P 命令问题(未记录?)

4

我有一个场景:

FORFILES /P "C:\users\DominiqueGerry\Work Files\" /S /M *.doc /C "cmd /c echo @fsize"

出现错误:

错误:无效的参数/选项 - '@fsize'。

输入 "FORFILES /?" 以获取用法说明。

但是当我去掉斜杠后,它可以正常工作:

FORFILES /P "C:\users\DominiqueGerry\Work Files" /S /M *.doc /C "cmd /c echo @fsize"

我不理解为什么这个命令在没有反斜杠的情况下不能正常工作,但是有反斜杠时也不能正常工作。我找不到任何官方文件来解释这个问题,并且运行forfiles /?时也没有看到任何相关说明。如果您能提供帮助,我将不胜感激。
最好的部分是,错误甚至与问题本身无关。

2
因为末尾的反斜杠对最后一个双引号进行了转义。将会发布答案并尝试解释。 - Gerhard
有些命令需要一个尾随的反斜杠,有些则是可选的(如xcopy),而有些则不需要。对于命令来说,没有标准。每个程序员在编写时都会面临特定的问题,因此会采取自己的方式。Windows基本功能试图修复错误路径,假设它不能与正确路径混淆。 - catcat
使用 forfiles 命令来输出文件大小是一个非常慢的方法,因为它会为每个文件启动一个新的命令进程。这个输出被 forfiles 捕获并在执行 forfiles 的 cmd 进程中输出。对于这个任务来说,最好使用 for 命令和批处理文件 cmd 行 for /R "C:\users\DominiqueGerry\Work Files" %%I in (*.doc) do echo %%~zI。只有在使用 forfiles 选项 /D 时,forfiles 才比 for 更有用,而通常基于最后修改日期的文件/文件夹复制/移动任务更适合使用 robocopy 或旧版的 xcopy - Mofi
@Mofi。谢谢你,但我实际上使用了forfiles /?帮助中的一个直接示例。当运行帮助时,您可以在示例的倒数第二行看到它。@catcat,感谢您的评论,但有些需要\,有些则不需要,这并不能真正解释问题所在。 - Gerry
2个回答

6
说实话,我不认为官方帮助文档中有关于这个问题的记录(至少我没有看到),但实际上发生的事情是,尾随的反斜杠实际上是转义了最后一个双引号。在我看来,这实际上是一个 bug。
错误不相关的原因很简单,因为 forfiles 命令检测到格式错误,由于缺少被反斜杠转义的双引号。
如果您的路径中没有空格,您会发现当没有双引号时不会出现这种情况:
FORFILES /P C:\users\DominiqueGerry\WorkFiles\ /S /M *.doc /C "cmd /c echo @fsize"

不会给你错误提示,只是因为反斜杠没有任何有效的字符需要转义,问题是,在路径中有一个空格,所以你必须使用双引号。所以最好保留双引号而不添加尾随的反斜杠:

FORFILES /P "C:\users\DominiqueGerry\Work Files" /S /M *.doc /C "cmd /c echo @fsize"

如果您坚持使用反斜杠,请将其加倍转义。

FORFILES /P "C:\users\DominiqueGerry\Work Files\\" /S /M *.doc /C "cmd /c echo @fsize"

另外,正如@aschipfl在评论中提到的那样,您可以使用 .

FORFILES /P "C:\users\DominiqueGerry\Work Files\." /S /M *.doc /C "cmd /c echo @fsize"

1
forfiles.exe对反斜杠的特殊解释是有意而非错误。原因与reg.exe解释在"\左侧的反斜杠作为引号/反斜杠转义字符的原因相同。这使得可以定义一个命令参数字符串(forfiles)或数据字符串(reg),其中包含双引号,包括双引号参数字符串的开头和结尾。但所有可能的解决方案都是可以接受的。 - Mofi
3
您说得对,Microsoft的[forfiles](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/forfiles)文档应该解释“forfiles”如何特殊解析反斜杠。我已经要求更正官方页面示例中的错误一次,并且可能还会要求扩展来解释“forfiles”中所有参数字符串中反斜杠的特殊解析。[reg add](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/reg-add)文档也需要扩展以涉及“\”解析。 - Mofi
我不认为这是一个错误,原因如下:反斜杠是Windows默认的目录分隔符,它只应在分隔路径组件时使用。最后一个组件后面没有任何内容,因此不应该有分隔符。 - Compo
@Compo,是的,我明白这一点,所以我说在我的想法中这是一个错误,纯粹是因为文档中没有提到这些。对我来说问题在于,forfiles不是内置的批处理函数,但你只能通过命令行解释器(在标准条件下)来使用它,即使标准帮助也只能通过cmd.exe显示,所以我希望文档中也应该包含这一点,正如Mofi在他的评论中提到的那样,否则就被认为是一个错误.. 对我来说 :) 所以请不要引用我说这是一个实际的错误。如果某些东西不能按预期工作,我只是希望在文档中阅读原因。 - Gerhard
其他命令工具允许最终用户忽略标准约定的事实并不意味着这个命令工具的开发者是错误的,最终用户才是! - Compo
显示剩余6条评论

0

将编译为可执行文件的 C/C++ 源代码遵循 解析 C++ 命令行参数

Microsoft C/C++启动代码在解释操作系统命令行中给出的参数时使用以下规则:
  • 参数由空格或制表符分隔。
  • 插入符号(^)不被识别为转义字符或分隔符。该字符在传递到程序的argv数组之前,由操作系统的命令行解析器完全处理。
  • 用双引号括起来的字符串("string")被解释为单个参数,无论其中包含的空格如何。引号内的字符串可以嵌入到一个参数中。
  • 反斜杠(\)被直接解释,除非它们紧接在双引号之前。
  • 如果偶数个反斜杠后跟着一个双引号,则每对反斜杠都在argv数组中放置一个反斜杠,并将双引号解释为字符串定界符。
  • 如果奇数个反斜杠后跟着一个双引号,则每对反斜杠都在argv数组中放置一个反斜杠,并且剩余的反斜杠“转义”了双引号,导致一个字面上的双引号(")被放置在argv中。

这在C++程序中非常常见。命令解释器在C++参数处理被建立之前就已经存在了。reg.exe和其他从C++源代码编译的程序通常具有此参数处理。

forfiles.exe不是命令解释器的内置命令,因此cmd.exe的内置帮助将不会告诉您外部可执行文件的行为方式。

正如您发现的那样,您可以使用反斜杠来转义双引号,即\"。这允许您在双引号内部的字符串中拥有双引号,即"\"string\"",以便传递给参数的程序保留引号。要转义反斜杠,请将其加倍,即\\

您收到的错误是一对双引号中的1个被删除,而转义的双引号被保留,因此剩余的双引号导致语法错误。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接