如何使用Windows forfiles命令的完整path运行命令?

我试图运行以下命令:

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的path包含空格。 通常引用整个论点来解决这个问题。 但是,似乎没有办法通过双引号。

那么, 如何使用Windows forfiles命令的完整path运行命令?

在第一次尝试时,您试图在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以及@path所有其他文件名和路径相关的@ -style变量forfiles扩展为已引用的值。


最初,我完全忘记了cmd试图去掉引号的事实。 克里托斯基里亚克的回答让我想起了这件事 。 所以如果你喜欢我的回答,请不要忘记给他们点数!

这不是在这里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要求引号用\来转义,所以我们需要写:

 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\"" 

(请注意, CMD所有引号都会被转义,但外部引号是FORFILES因此不会被转义。)