gpt4 book ai didi

batch-file - 如何在for循环中处理路径名中的右括号?

转载 作者:行者123 更新时间:2023-12-03 16:39:30 24 4
gpt4 key购买 nike

对于必须在for/f循环中运行的程序,我有一个长路径名,其中包括一个右括号“)”,并且需要从中解析输出:

for /f "tokens=1" %%G in ('"C:\Documents and Settings\myaccount\Desktop\Test_release (x86)\program.exe" list') do (echo Will do something with %%G)

...其中“列表”是传递给我的程序的参数。我收到错误消息“'C:\Documents'无法识别为内部或外部命令,可操作程序或批处理文件。”

我确实知道问题在于,右括号实际上会关闭“for”块,因此结尾的双引号不会被“看到”,因此长路径名不再包含在双引号中。我不明白为什么会这样,因为我的路径被双引号引起了?我也尝试过usebackq选项:
for /f "usebackq tokens=1" %%G in (`"C:\Documents and Settings\myaccount\Desktop\Test_release (x86)\program.exe" list`) do (echo Will do something with %%G)

...没有更好的结果。我试图像这样的“^)”或这样的“^^)”那样逃避,无所事事。尝试将双引号加倍:
for /f "tokens=1" %%G in ('""C:\Documents and Settings\myaccount\Desktop\Test_release (x86)\program.exe"" list') do (echo Will do something with %%G)

仍然无法正常工作。

此外,实际上,我使用的是保存路径的变量,该变量是事先不知道的(从%CD%构建),并且 EnableDelayedExpansion 被激活。我尝试了延迟扩展(在其他情况下确实解决了类似问题),以防止变量在读取时扩展,并在执行时延迟:
setlocal EnableDelayedExpansion
set _var=%CD%\program.exe
@REM _var now contains C:\Documents and Settings\myaccount\Desktop\Test_release (x86)\program.exe
for /f "tokens=1" %%G in ('"!_var!" list') do (echo %%G)
endlocal

还是不行,不明白为什么。

但是,在上述代码中双引号加倍,延迟扩展:
for /f "tokens=1" %%G in ('""!_var!"" list') do (echo %%G)

确实有效! ...为什么...为什么要这样做???它有什么作用?我不明白我也担心在某些特定情况下可能会引起问题。

任何想法?

最佳答案

在此问题的答案中的注释表示XP提供了与新的Windows版本不同的行为。

XP中存在一个已知的FOR/F错误:http://www.dostips.com/forum/viewtopic.php?p=9062#p9062。但是此问题与该错误无关。

实际的问题源于FOR/F如何在IN()子句中执行命令。它使用CMD \C command(请参阅How does the Windows Command Interpreter (CMD.EXE) parse scripts?)

您可以通过将这一行添加到Aacini的PROG.BAT示例中来观察这种行为。

echo cmdcmdline=%cmdcmdline%

下一个问题涉及CMD如何处理/C命令中出现的引号,以及为什么XP的行为不同于最新的Windows版本。

此命令在XP中失败,但在Vista及更高版本中成功:
for /f "delims=" %a in ('"test (this)\prog" args') do @echo %a

FOR尝试执行的命令(%cmdcmdline%)在两个版本中都是相同的(忽略%COMSPEC%的差异):
C:\Windows\system32\cmd.exe /c "test (this)\prog" args

XP在如何处理报价方面存在CMD设计缺陷。甚至会记录该缺陷(但不能识别为缺陷)。 Vista及更高版本部分修复了设计缺陷,但不必费心去纠正文档。

这是HELP CMD的摘录
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.

我们希望CMD遵循规则1,以便保留引号,但是 ()违反XP上的特殊字符约束,因此遵循规则2,CMD尝试执行
test (this)\prog args

这很明显为什么会失败!

我无法想到规则1中存在特殊字符约束的任何原因。它违背了MS尝试执行的操作的全部目的。

显然,设计缺陷已在Vista和更高版本中得到部分修复,但他们尚未更新HELP文档。 Vista会忽略特殊字符 (),并使用规则1处理命令,保留引号,然后一切正常。

更新2015-05-17:不幸的是,Vista及更高版本仍然将 @^&视为特殊字符,即使它们是文件名中的有效字符也是如此。当然 <>|被视为特殊字符,但是它们在文件名中始终无效。因此,对于Vista及更高版本,规则1的文档应阅读 where special is one of: &<>@^|

我已经跟踪了每个人都记录的行为,并且与上述行为完全一致。

有一种方法可以在XP上执行命令而无需使用延迟的扩展变量,并且它与Vista及更高版本兼容。
for /f "delims=" %a in ('^""test (this)\prog" args^"') do @echo %a

开头和结尾的引号被转义,以便 )不会干扰FOR解析器。为IN()子句执行的命令是
C:\Windows\system32\cmd.exe /c ""test (this)\prog" args"

XP和Vista都遵循规则2,因为引号多于两个,因此CMD执行
"test (this)\prog" args

一切正常!

该答案的其余部分已过时,但保留下来可以为现有注释提供上下文。

您的第一个代码示例应该可以运行;它不能(不应该这样)给出您描述的错误消息。错误消息在第一个空格处断开了路径,这意味着该路径未被引用或转义。但是您“确信”它被引用了。

该问题的关键是帖子结尾附近的三条信息:
  • 您实际上正在使用延迟扩展的变量
  • 这不起作用:for /f "tokens=1" %%G in ('"!_var!" list') do (echo %%G)
  • 这有效:for /f "tokens=1" %%G in ('""!_var!"" list') do (echo %%G)

  • 如果已引用var的值,则将得到您正在描述的行为。

    var的值必须为 "C:\Documents and Settings\myaccount\Desktop\Test_release (x86)\program.exe",包括引号。

    为了使此说明更易读,我将缩短 "test (this)\prog.exe"的路径
    "!var!"失败,因为它扩展为 ""test (this)\prog.exe"",从而有效地取消了路径的引用。该字符串包含三个区域,两个区域用引号引起来,而一个区域的中间则没有:

    "empty quoted area"unquoted path"empty quoted area"


    ""!var!""之所以有效,是因为它扩展为 """test (this)\prog.exe""",并且现在再次引用了该路径。现在,字符串中有五个区域:

    "empty quoted area"empty unquoted area"quoted path"empty unquoted area"empty quoted area"



    关于如何进行的简单答案:

    如果已经引用了var的值,则只需使用 !var! Edit-在XP上不起作用:“!var!”可以在上同时使用

    如果未引用var的值,则使用 "!var!" 编辑-在XP上不起作用:“”!var!“”在上均适用

    关于batch-file - 如何在for循环中处理路径名中的右括号?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8189553/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com