3

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

forfiles /p ..\Schemas /m *.xsd /c "cmd /c ""C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.6.1 Tools\xsd.exe @path /classes"""

但是,它失败了:

ERROR: Invalid argument/option - 'Files'.
Type "FORFILES /?" for usage.

这些也不起作用:

forfiles /p ..\Schemas /m *.xsd /c "cmd /c \"C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.6.1 Tools\xsd.exe\" @path /classes"

forfiles /p ..\Schemas /m *.xsd /c "cmd /c ^"C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.6.1 Tools\xsd.exe^" @path /classes"

它肯定会失败,因为传递给的路径cmd包含空格。您通常通过引用整个论点来解决这个问题。但是,似乎没有办法传递双引号。

那么,如何从 Windows forfiles 命令运行具有完整路径的命令?

4

2 回答 2

3

这不是forfiles这里的错。这是 cmd.exe 处理引号的方式。它本质上是为了自己的利益而试图变得过于聪明。该CMD /C命令可以将任意行作为命令,包括包含空格的行;但是,如果后面给出的命令行CMD /C以引号开头,它会在尝试执行之前从该行中删除第一个和最后一个引号。因此,这两行是完全等价的:

cmd /c echo hello
cmd /c "echo hello"

现在的问题是引号在以下命令中被剥离:

cmd /c "C:\Program Files\xyz\abc.exe" one two

为了让它做你想做的事,你需要把整个事情用引号引起来(内引号不需要转义):

cmd /c ""C:\Program Files\xyz\abc.exe" one two"

现在,您可以将其放入FORFILES命令中。FORFILES 要求引号用 a 转义\,所以我们需要写:

forfiles /c "cmd /c \"\"C:\Program Files\xyz\abc.exe\" one two\""

或者在您的特定情况下:

forfiles /p ..\Schemas /m *.xsd /c "cmd /c \"\"C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.6.1 Tools\xsd.exe\" @path /classes\""

(请注意,所有引号 forCMD都被转义,但外部引号是 forFORFILES所以不会转义。)

于 2016-09-12T16:15:42.477 回答
3

在您的第一次尝试中,您尝试在整个命令行之后放置(附加)引号,cmd /c而不是仅在可执行文件的路径之后,这将失败,因为cmd尝试将整行作为命令查找并执行。xsd.exe因此,您需要在命令行末尾而不是在命令行末尾立即移动右引号。

然而,总的来说,这里的主要问题是cmdforfiles处理引号的方式不同。forfiles用于\"转义引用,但cmd不关心反斜杠。此外,如果您的代码出现在带括号的代码块中,如果路径中的文字括号没有出现在cmd. 最后,cmd可能会尝试去掉引号(出乎意料),这可能会导致更多问题。

为了解决这一切,使用另一种在命令行后面提供文字引号的方法/Cforfiles支持通过0xHH符号的十六进制代码指定字符;所以声明0x22会隐藏父实例的引号,cmd直到实际执行命令行:

forfiles /p ..\Schemas /m *.xsd /c "cmd /c 0x220x22C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.6.1 Tools\xsd.exe0x22 @path /classes0x22"

这将导致执行以下命令行("D:\Data\Schemas\sample.xsd"用作 的示例值@path):

cmd /c ""C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.6.1 Tools\xsd.exe" "D:\Data\Schemas\sample.xsd" /classes"

最后,通过 去掉最外层的引号后cmd,执行以下命令行:

"C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.6.1 Tools\xsd.exe" "D:\Data\Schemas\sample.xsd" /classes

请注意@path,以及所有其他与文件名和路径相关的@样式变量都forfiles扩展为已引用的值。


cmd最初,我完全忘记了试图去掉引号的事实。Klitos Kyriacou回答让我想起了这一点;所以如果你喜欢我的回答,请不要忘记给他们点赞!

于 2016-09-12T15:11:50.063 回答