为什么forfiles命令会吞掉第一个参数?

3
我正在尝试使用cmd的forfiles来转换VS2008中的每个模板,类似于Get Visual Studio to run a T4 Template on every build
如果我执行
forfiles /m "*.tt" /s /c "\"%CommonProgramFiles(x86)%\Microsoft Shared\TextTemplating\1.2\TextTransform.exe\" @file"

然后我收到 TextTransform.exe 的错误信息(一屏幕文字说明需要传递的参数)。

如果我执行以下操作:

forfiles /m "*.tt" /s /c "cmd /c echo Transforming @path && \"%CommonProgramFiles(x86)%\Microsoft Shared\TextTemplating\1.2\TextTransform.exe\" @file"

然后它就完美地工作了。

为了调试这个问题,我创建了一个简单的命令行程序,名为debugargs,它只打印它接收到的参数数量和它们的值。然后一些实验表明,直接将命令传递给forfiles的第一种形式会导致第一个参数被吞噬。例如:

forfiles /m "*.tt" /s /c "debugargs.exe 1 2 3"

给出输出

2 arguments supplied
#1: 2
#2: 3

我能找到的文档非常有限,也没有提到这种可能性。这只是一个不常见的错误吗,还是我漏掉了什么?


有趣。我在网上看到的所有示例都使用“/c“cmd /c ...”;没有一个直接调用单独的exe文件。 - Nate Hekman
1
奇怪。我发现如果前两个参数中的任何一个是EXE,则该EXE将运行并接收剩余的参数(即param3+)。但是,如果参数是.BAT,则第二个参数将运行,并接收参数3+。 - Magoo
@PeterWright,有趣的观察。这似乎稍微有些复杂。仅查看第二个参数是exe的情况:如果第一个参数不是文件,则会出现“ERROR: The system cannot find the file specified.”。如果第一个参数是例如文本文件,则会得到“ERROR: "test.txt" is not a valid executable.”因此,在那里真正起作用的唯一虚拟文件是现有的.bat.cmd文件。奇怪。 - Peter Taylor
3个回答

3
这似乎是forfiles调用.exe时的一个错误。凭直觉,我扩展了我的debugargs程序以打印完整的命令行。
X:\MyProject>forfiles /m "*.tt" /s /c "debugargs.exe 1 2 @file"

2 arguments supplied
#1: 2
#2: Urls.tt
Full command line: 1 2 "Urls.tt"

因此,最合适的解决方法是将可执行文件名重复一遍:
forfiles /m "*.tt" /s /c "debugargs.exe debugargs.exe 1 2 @file"

另一个解决方法是使用cmd /c来调用。然而,需要注意的是,如果您需要引用可执行文件的路径(例如,因为它包含空格),则需要在前面添加额外的解决方法@

forfiles /m "*.tt" /s /c "cmd /c @\"debugargs.exe\" 1 2 @file"

这里的@字符有什么作用?我想使用带有空格的可执行文件路径的FORFILES,但无法使其正常工作。就像@字符启用了\"的使用一样,我已经尝试过但没有使用@并且没有成功。是否有一个地方可以获取更多关于此属性的信息?谢谢。 - simpLE MAn
抱歉,我记不起来了。我很少使用cmd:我更喜欢使用cygwin bash。 - Peter Taylor

0

我也在forfiles中重现了这个问题。你可以通过在命令前使用cmd /c来解决,或者你可以过渡到PowerShell,在那里相当的命令可能是这样的(未经测试):

get-childitem . -filter "*.tt" -recurse | foreach-object {
  & "${ENV:CommonProgramFiles(x86)}\Microsoft Shared\TextTemplating\1.2\TextTransform.exe" "`"$($_.Name)`""
}

Bill


我认为PowerShell不是一个选项(除非我从“cmd”中调用它),因为VS2008会将我给出的命令转储到批处理文件中执行。 - Peter Taylor

0

我也遇到了这个问题。我发现的解决方法是在命令和第一个参数之间添加一个额外的空格!所以,当我尝试执行以下操作时:

FORFILES /s /m *.dll /c "python \"c:\path\to\script.py\" -t arg1 etc"

Python 正在尝试查找要执行的文件 "arg1",但如果我只是将其更改为:

FORFILES /s /m *.dll /c "python  \"c:\path\to\script.py\" -t arg1 etc"

这真的有效!


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