loops - 如何在 set 命令中使用括号转义变量?

标签 loops variables batch-file for-loop parentheses

当我有

SET IrfanFile32=i_view32.exe    
FOR /F "tokens=*" %%a IN ('dir /b /s "%ProgramFiles%\%IrfanFile32%" 2^>NUL') DO SET IrfanPath=%%a

如果找到相应的文件,这将导致设置所需的变量。但是当我将最后一行更改为

FOR /F "tokens=*" %%a IN ('dir /b /s "%PROGRAMFILES(X86)%\%IrfanFile32%"') DO SET IrfanPath=%%a

它说“\IrfanView\i_view32.exe”此时无法在语法上进行处理,这显然是指 set 命令。 (echo 的作用是给出正确的结果)。 SET 的括号似乎有问题,但是当我认为我可以通过使用引号来解决这个问题时

FOR /F "tokens=*" %%a IN ('dir /b /s "%PROGRAMFILES(X86)%\%IrfanFile32%"') DO SET "IrfanPath=%%a"

我注意到它并不能解决问题。 我错过了什么/我怎样才能实现这个目标? (我读到了关于普通变量的延迟扩展,但这适用于像 %%a 这样的循环变量吗?如果是的话:如何?)


整体代码如下:

REM @echo off
SETLOCAL ENABLEDELAYEDEXPANSION
SET IrfanFile32=i_view32.exe
SET IrfanFile64=i_view64.exe
SET IrfanParams=""
SET SourcePath=%~1\nul
:Start
FOR /F "tokens=3,4,5,6,7,8,9" %%a IN ('REG QUERY HKCU\Environment /v IrfanPath ^|find "IrfanPath"') DO (
  REM echo %IrfanPath%
  SET IrfanPath=%%a %%b %%c %%d %%e %%f %%g
)
echo.
IF NOT DEFINED IrfanPath (GOTO Init) ELSE (GOTO Main)
:Init
  echo Dies scheint mein erster Start auf diesem System zu sein. 
  echo Ich benötige IrfanView (inkl. JPG_TRANSFORM Plugin) um zu funktionieren
  echo und suche nun im Ordner %ProgramFiles% und allen Unterverzeichnissen 
  echo nach IrfanViews Startdatei namens %IrfanFile32% bzw. %IrfanFile64%.
  echo.
  IF EXIST "%PROGRAMFILES(X86)%" echo 64bit Betriebssystem gefunden, suche zusätzlich in %PROGRAMFILES(X86)%.
  echo.
  FOR /F "tokens=*" %%a IN ('dir /b /s "%ProgramFiles%\%IrfanFile32%" 2^>NUL') DO SET IrfanPath=%%a
  FOR /F "tokens=*" %%a IN ('dir /b /s "%ProgramFiles%\%IrfanFile64%" 2^>NUL') DO SET IrfanPath=%%a
  FOR /F "tokens=*" %%a IN ('dir /b /s "%PROGRAMFILES(X86)%\%IrfanFile32%"') DO SET IrfanPath=%%a
  IF DEFINED IrfanPath (
    echo Ich habe IrfanView hier gefunden: %IrfanPath%
    :Entscheidung
    SET /P PathKorrekt=Ist das der gewünschte Pfad? [^(J^)a/^(N^)ein]
    if /i {!PathKorrekt!}=={j} (goto :yes)
    if /i {!PathKorrekt!}=={ja} (goto :yes)
    if /i {!PathKorrekt!}=={n} (goto :no)
    if /i {!PathKorrekt!}=={nein} (goto :no)
    echo Das war keine gültige Antwort. Benutze ja, nein, j oder n. 
    GOTO Entscheidung

    :yes
    REG ADD HKCU\Environment /v IrfanPath /d "%IrfanPath%" >nul
    GOTO Start
  )
  :no
  SET /P IrfanPath=Bitte gib den Pfad zur %IrfanFile32% bzw. %IrfanFile64% an: 
  IF NOT EXIST "%IrfanPath%\%IrfanFile32%" (
    IF NOT EXIST "%IrfanPath%\%IrfanFile64%" (
      echo Keine %IrfanFile32% oder %IrfanFile64% in diesem Ordner gefunden, nochmal bitte.
    GOTO no
    )
  ) ELSE (
    IF EXIST "%IrfanPath%\%IrfanFile32%" (
      REG ADD HKCU\Environment /v IrfanPath /d "%IrfanPath%\%IrfanFile32%"
    )
    IF EXIST "%IrfanPath%\%IrfanFile64%" (
      REG ADD HKCU\Environment /v IrfanPath /d "%IrfanPath%\%IrfanFile64%"
    )
    PAUSE > NUL
    GOTO Start
  )
) else GOTO Main

:Main
REM more code here

最佳答案

您的代码中一定有更多内容没有显示,因为您发布的代码由于多种原因无法给出您所描述的错误:

  • SET 命令不关心括号
  • %%a 这样的 FOR 变量扩展可以防止括号等有毒字符
  • 在 SET 语句中添加引号可以防止有毒字 rune 字(您无论如何都没有)

错误一定是在代码的其他地方。我的猜测是您有一个带括号的 IF 或 FOR block ,其中包含未加引号的 %IrfanPath%,由于 Program Files 中的 ) ,这会过早关闭带括号的 block (x86)

如果您在脚本中禁用 ECHO OFF(保持 ECHO ON),您可能会很快发现问题。

更新以回应已编辑的问题:

问题正如我所预测的那样 - 在代码后面带括号的 IF 语句中:

  IF DEFINED IrfanPath (
    echo Ich habe IrfanView hier gefunden: %IrfanPath%
    ... additional code ...
  )

您的 %IrfanPath% 包含 ),并且未加引号。那么展开后,逻辑上就变成了:

  IF DEFINED IrfanPath (
    echo Ich habe IrfanView hier gefunden: C:\Program Files (x86
  )
  \IrfanView\i_view32.exe
    ... additional code ...
  )

这就是错误消息的来源。

最简单的解决方案是在扩展路径周围加上引号:

  IF DEFINED IrfanPath (
    echo Ich habe IrfanView hier gefunden: "%IrfanPath%"
    ... additional code ...
  )

我相信您的代码将正常工作。但是,您使用 GOTO 分支到带括号的 IF block 内的 :label,这是一个很大的禁忌,因为它会破坏 IF block 。您还有一个不平衡的右括号,它有效地充当注释:

) else GOTO Main

参见(Windows batch) Goto within if block behaves very strangely了解更多信息。

我认为您的代码是一种特殊情况,它恰好可以正常工作。但更常见的是,如果您不了解其机制,它会导致难以调试的疯狂结果。

我将按如下方式重组您的代码:

REM @echo off
setlocal DisableDelayedExpansion
SET IrfanFile32=i_view32.exe
SET IrfanFile64=i_view64.exe
SET IrfanParams=""
SET "SourcePath=%~1\nul"
:Start
FOR /F "tokens=3,4,5,6,7,8,9" %%a IN ('REG QUERY HKCU\Environment /v IrfanPath ^|find "IrfanPath"') DO (
  REM echo %IrfanPath%
  SET IrfanPath=%%a %%b %%c %%d %%e %%f %%g
)
echo.
IF NOT DEFINED IrfanPath (GOTO Init) ELSE (GOTO Main)
:Init
  echo Dies scheint mein erster Start auf diesem System zu sein. 
  echo Ich benötige IrfanView (inkl. JPG_TRANSFORM Plugin) um zu funktionieren
  echo und suche nun im Ordner %ProgramFiles% und allen Unterverzeichnissen 
  echo nach IrfanViews Startdatei namens %IrfanFile32% bzw. %IrfanFile64%.
  echo.
  IF EXIST "%PROGRAMFILES(X86)%" echo 64bit Betriebssystem gefunden, suche zusätzlich in %PROGRAMFILES(X86)%.
  echo.
  FOR /F "tokens=*" %%a IN ('dir /b /s "%ProgramFiles%\%IrfanFile32%" 2^>NUL') DO SET IrfanPath=%%a
  FOR /F "tokens=*" %%a IN ('dir /b /s "%ProgramFiles%\%IrfanFile64%" 2^>NUL') DO SET IrfanPath=%%a
  FOR /F "tokens=*" %%a IN ('dir /b /s "%PROGRAMFILES(X86)%\%IrfanFile32%"') DO SET IrfanPath=%%a

  if not defined IrfanPath goto :no

  echo Ich habe IrfanView hier gefunden: %IrfanPath%
:Entscheidung
  SET /P PathKorrekt=Ist das der gewünschte Pfad? [^(J^)a/^(N^)ein]
  if /i "%PathKorrekt%"=="j" (goto :yes)
  if /i "%PathKorrekt%"=="ja" (goto :yes)
  if /i "%PathKorrekt%"=="n" (goto :no)
  if /i "%PathKorrekt%"=="nein" (goto :no)
  echo Das war keine gültige Antwort. Benutze ja, nein, j oder n.
  GOTO Entscheidung

:yes
  REG ADD HKCU\Environment /v IrfanPath /d "%IrfanPath%" >nul
  GOTO Start

:no
  SET /P IrfanPath=Bitte gib den Pfad zur %IrfanFile32% bzw. %IrfanFile64% an:
  IF NOT EXIST "%IrfanPath%\%IrfanFile32%" (
    IF NOT EXIST "%IrfanPath%\%IrfanFile64%" (
      echo Keine %IrfanFile32% oder %IrfanFile64% in diesem Ordner gefunden, nochmal bitte.
      GOTO no
    )
  ) ELSE (
    IF EXIST "%IrfanPath%\%IrfanFile32%" (
      REG ADD HKCU\Environment /v IrfanPath /d "%IrfanPath%\%IrfanFile32%"
    )
    IF EXIST "%IrfanPath%\%IrfanFile64%" (
      REG ADD HKCU\Environment /v IrfanPath /d "%IrfanPath%\%IrfanFile64%"
    )
    PAUSE > NUL
    GOTO Start
  )

:Main
REM more code here

请注意,此结构不再需要延迟扩展。

关于loops - 如何在 set 命令中使用括号转义变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35819981/

相关文章:

python - 如果循环更新其自身之外的内容 - 如何构建等效的或 lambda/列表理解?

php - 如何使用phpmailer向多个地址逐个发送邮件?

c - 在 C 中处理动态整数类型?

windows - 在批处理文件中实现定时输入。 (倒计时一分钟)

java - 如何要求多个输入并在用户输入 0 时停止?

Javascript 未在 $.each() 中返回

windows - xcopy语法? (批)

powershell - 如何从 powershell 调用批处理以便我可以在 powershell 控制台中看到实时输出

c++ - 有哪些不同的初始化方式

variables - 将客户端 js 变量传递到服务器端 jscript