如何在 set 命令中使用括号转义变量?
How to escape variables with parentheses inside set command?
当我有
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命令。 (回声的工作方式给出了正确的结果)。
SET 的括号似乎有问题,但是当我认为我可以通过使用引号
来解决这个问题时
FOR /F "tokens=*" %%a IN ('dir /b /s "%PROGRAMFILES(X86)%\%IrfanFile32%"') DO SET "IrfanPath=%%a"
我注意到它没有修复它。
我做了什么 miss/how 我能做到吗? (我阅读了关于普通变量的延迟扩展,但它是否适用于像 %%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 语句中添加引号可以防止有毒字符文字(无论如何您都没有)
错误一定是在您的代码中的其他地方。我猜你有一个带括号的 IF 或 FOR 块,其中包含一个未加引号的 %IrfanPath%
,由于 Program Files (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 块中的 :label ,这是一个很大的禁忌,因为它会破坏 IF 块。您还有一个不平衡的右括号,它有效地用作评论:
) 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
请注意,此结构不再需要延迟扩展。
当我有
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命令。 (回声的工作方式给出了正确的结果)。 SET 的括号似乎有问题,但是当我认为我可以通过使用引号
来解决这个问题时FOR /F "tokens=*" %%a IN ('dir /b /s "%PROGRAMFILES(X86)%\%IrfanFile32%"') DO SET "IrfanPath=%%a"
我注意到它没有修复它。 我做了什么 miss/how 我能做到吗? (我阅读了关于普通变量的延迟扩展,但它是否适用于像 %%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 语句中添加引号可以防止有毒字符文字(无论如何您都没有)
错误一定是在您的代码中的其他地方。我猜你有一个带括号的 IF 或 FOR 块,其中包含一个未加引号的 %IrfanPath%
,由于 Program Files (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 块中的 :label ,这是一个很大的禁忌,因为它会破坏 IF 块。您还有一个不平衡的右括号,它有效地用作评论:
) 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
请注意,此结构不再需要延迟扩展。