我不明白批处理命令与命令for一起使用时的工作方式。/f
我试图循环执行可执行文件的输出。结果发现可执行文件不存在,这很好。
但脚本似乎并没有得到关于错误路径的预期错误,而是自发地错误地标记了字符串。这让我陷入了困境,认为我已经格式化了 for 循环和/或错误地使用了引号或反引号。
在该位置放置可执行文件可以解决该问题,使其看起来路径字符串标记化依赖于该路径上实际文件的存在。
为什么下面的批处理文件
@echo off
for /f "usebackq delims=" %%i in ( `"C:\Program Files\BOGUS_PATH\FAKE.exe"`) do (
rem
)
Run Code Online (Sandbox Code Playgroud)
输出'C:\Program' is not recognized as an internal or external command, operable program or batch file.而不是The system cannot find the path specified.?
首先,我最讨厌的一点是,usebackq不需要。更简单且功能等效的命令是
@echo off
for /f "delims=" %%i in ('"C:\Program Files\BOGUS_PATH\FAKE.exe"') do (
rem
)
Run Code Online (Sandbox Code Playgroud)
唯一usebackq需要的时间是当您尝试读取文件并且文件路径包含空格等标记分隔符时。
for /f "usebackq" %%A in ('"some file.txt"')
Run Code Online (Sandbox Code Playgroud)
所有其他情况都可以使用“正常”形式
for /f %%A in (fileName) do...
for /f %%A in ("string") do...
for /f %%A in ('someCommand') do...
Run Code Online (Sandbox Code Playgroud)
现在回答您的实际问题:-)
文件的存在或不存在实际上并不会改变解析。
首先,您需要了解当您尝试从命令行执行不存在的程序时可能出现的错误消息。有以下三种可能:
1)如果“命令”在第二个位置以外的任何地方都包含冒号,那么您可能会得到以下结果
c:\test\>abc:fake.exe
The filename, directory name, or volume label syntax is incorrect.
c:\test\>abc:\test\fake.exe
The filename, directory name, or volume label syntax is incorrect.
Run Code Online (Sandbox Code Playgroud)
或者有时您会遇到下一个可能的错误。关于您收到哪条消息的规则对我来说并不明显,而且我认为弄清楚确切的规则还不够重要。
2)如果“命令”包含指示路径的反斜杠,并且该路径无效,那么您会得到
c:\test\>c:bogus\fake.exe
The system cannot find the path specified.
c:\test\>\bogus\fake.exe
The system cannot find the path specified.
c:\test\>abc:bogus\fake.exe
The system cannot find the path specified.
Run Code Online (Sandbox Code Playgroud)
3)如果找不到可执行文件,并且“命令”不包含路径信息或提供的路径有效,那么您会得到
C:\test\>fake.exe
'fake.exe' is not recognized as an internal or external command,
operable program or batch file.
C:\test>c:\test\fake.exe
'c:\test\fake.exe' is not recognized as an internal or external command,
operable program or batch file.
Run Code Online (Sandbox Code Playgroud)
最后一个难题是为什么"C:\Program Files\BOGUS_PATH\FAKE.exe"给出错误 3) 而不是 2)
如果您从带有引号的命令行执行,那么您将得到预期的结果:
C:\test>"C:\Program Files\BOGUS_PATH\FAKE.exe"
The system cannot find the path specified.
Run Code Online (Sandbox Code Playgroud)
如果您从不带引号的命令行执行,那么您将得到以下预期结果:
C:\test>C:\Program Files\BOGUS_PATH\FAKE.exe
'C:\Program' is not recognized as an internal or external command,
operable program or batch file.
Run Code Online (Sandbox Code Playgroud)
您的脚本包含引号,因此您会期望是前者,但您得到的是后者。
理解这一点有两个部分。
首先,FOR /F 通过执行来执行命令
C:\WINDOWS\system32\cmd.exe /c "C:\Program Files\BOGUS_PATH\FAKE.exe"
Run Code Online (Sandbox Code Playgroud)
您可能认为您的“命令”被引用了,但 cmd.exe 用引号玩游戏,这是解释的第二部分。cmd.exe的引用规则在帮助中有描述:
c:\test\>help cmd
Starts a new instance of the Windows command interpreter
...
If /C or /K is specified, then the remainder of the command line after
the switch is processed as a command line, where the following logic is
used to process quote (") characters:
1. If all of the following conditions are met, then quote characters
on the command line are preserved:
- no /S switch
- exactly two quote characters
- no special characters between the two quote characters,
where special is one of: &<>()@^|
- there are one or more whitespace characters between the
two quote characters
- the string between the two quote characters is the name
of an executable file.
2. Otherwise, old behavior is to see if the first character is
a quote character and if so, strip the leading character and
remove the last quote character on the command line, preserving
any text after the last quote character.
Run Code Online (Sandbox Code Playgroud)
除最后一个条件外,大多数条件1.均已满足- 该字符串未指向有效的可执行文件。所以使用规则,因此命令变成2.
C:\Program Files\BOGUS_PATH\FAKE.exe
Run Code Online (Sandbox Code Playgroud)
现在结果完全合理了——“命令”在空格处中断。
'C:\Program' is not recognized as an internal or external command,
operable program or batch file.
Run Code Online (Sandbox Code Playgroud)
如果您尝试使用 执行命令FOR /F,并且该命令必须用引号引起来,则必须在整个命令周围添加一组额外的引号。
for /f "delims=" %%A in ('""c:\some path\file.exe" "arg 1" arg2"') do ...
Run Code Online (Sandbox Code Playgroud)
但是如果路径或引用的参数中有有毒字符,上面的代码就会出现问题,因为额外的引号会弄乱引用。你可以逃脱像这样的有毒角色
for /f "delims=" %%A in ('""c:\some path\file.exe" "this^&that" arg2"') do ...
Run Code Online (Sandbox Code Playgroud)
但我发现这很尴尬,因为您在命令行上使用的命令与您在FOR /F. 我更喜欢转义额外的一组引号,以便在命令行上起作用的任何内容也可以在FOR /F.
for /f "delims=" %%A in ('^""c:\some path\file.exe" "this&that" arg2^"') do ...
Run Code Online (Sandbox Code Playgroud)