在 Batch 的 endlocal 之后保留变量
Keep variable after endlocal in Batch
我有一个文件夹结构,比如C:\Temp\,里面有很多文件夹和文件,每个文件夹里面有一个"callme.bat"。我想创建一个所谓的 main.bat,它在主 window 中一个接一个地调用 callme 文件。但是有一个问题,在 callme 文件中有一些包含“!”的回声。标记对我来说是什么问题。
我意识到 setlocal-endlocal 组合的问题,因为批处理脚本想要解释“!”内的消息。标记,所以我必须使用 endlocal,但如果我这样做了,我将无法 运行 callme bats。
callme.bat
@echo off
echo !!! hidden message !!! not hidden message
pause
main.bat 变体 1
@echo off
setlocal enabledelayedexpansion
set PATH=C:\Temp
for /F %%x in ('dir /B/A:D %PATH%') do (
set CURR_DIR=%PATH%\%%x
set ACTUAL_BATCH=!CURR_DIR!\callme.bat
echo !ACTUAL_BATCH!
call !ACTUAL_BATCH!
pause
)
pause
exit
main.bat 变体 2
@echo off
set PATH=C:\Temp
for /F %%x in ('dir /B/A:D %PATH%') do (
setlocal enabledelayedexpansion
set CURR_DIR=%PATH%\%%x
set ACTUAL_BATCH=!CURR_DIR!\callme.bat
echo !ACTUAL_BATCH!
ENDLOCAL & SET VAR=!ACTUAL_BATCH!
echo %VAR%
pause
)
pause
exit
main.bat 变体 3
@echo off
set PATH=C:\Temp
for /F %%x in ('dir /B/A:D %PATH%') do (
setlocal enabledelayedexpansion
set CURR_DIR=%PATH%\%%x
set ACTUAL_BATCH=!CURR_DIR!\callme.bat
echo !ACTUAL_BATCH!
REM source:
for /f "delims=" %%A in (""!ACTUAL_BATCH!"") do endlocal & set "VAR=%%~A"
echo %VAR%
call %VAR%
pause
)
pause
exit
所以我不知道该怎么办。有人有想法吗?
变体 1 的输出:
C:\Temp\callme.bat
not hidden message
C:\Temp\callme.bat
not hidden message
变体 2-3 的输出:
C:\Temp\callme.bat
ECHO is off.
C:\Temp\callme.bat
ECHO is off.
TL;DR
ENDLOCAL&set "varname=%sourcevarname%"
可能,其中 varname
是要设置的变量名,sourcevarname
是其值要分配给 varname
的变量 - 他们 CAN 是相同的名称,即使该语句在逻辑上显示为空 - 它从 setlocal/endlocal
块中导出变量。
要点:必须在一条物理线路上,必要时可以重复(即
ENDLOCAL&set "varname=%sourcevarname%"&set "varname2=%sourcevarname2%"
所以
ENDLOCAL&set "fred=%fred%"&set "bill=%george%"
完全有效,将 setlocal/endlocal 括号外的 fred
的值设置为其内部的最终值,将 bill
外部的值设置为 george
的最终值里面。
关于您的代码的一些要点:
永远不要使用 PATH
作为变量名,因为它会破坏用于搜索可执行文件的 PATH
变量。
使用扩展的 SET
语法 set "varname=content"
来避免训练空间的问题。
只需要使用setlocal DisableDelayedExpansion
关闭延迟扩展模式即可
@echo off
setlocal EnableDelayedExpansion
set MY_PATH=C:\Temp
for /F %%x in ('dir /B/A:D %PATH%') do (
set "CURR_DIR=%MY_PATH%\%%x"
set "ACTUAL_BATCH=!CURR_DIR!\callme.bat"
call :execute ACTUAL_BATCH
pause
)
pause
exit /b
:execute ACTUAL_BATCH
set "batFile=!%~1!"
echo Calling !batFile!
setlocal DisableDelayedExpansion
call %batFile%
endlocal
exit /b
我有一个文件夹结构,比如C:\Temp\,里面有很多文件夹和文件,每个文件夹里面有一个"callme.bat"。我想创建一个所谓的 main.bat,它在主 window 中一个接一个地调用 callme 文件。但是有一个问题,在 callme 文件中有一些包含“!”的回声。标记对我来说是什么问题。
我意识到 setlocal-endlocal 组合的问题,因为批处理脚本想要解释“!”内的消息。标记,所以我必须使用 endlocal,但如果我这样做了,我将无法 运行 callme bats。
callme.bat
@echo off
echo !!! hidden message !!! not hidden message
pause
main.bat 变体 1
@echo off
setlocal enabledelayedexpansion
set PATH=C:\Temp
for /F %%x in ('dir /B/A:D %PATH%') do (
set CURR_DIR=%PATH%\%%x
set ACTUAL_BATCH=!CURR_DIR!\callme.bat
echo !ACTUAL_BATCH!
call !ACTUAL_BATCH!
pause
)
pause
exit
main.bat 变体 2
@echo off
set PATH=C:\Temp
for /F %%x in ('dir /B/A:D %PATH%') do (
setlocal enabledelayedexpansion
set CURR_DIR=%PATH%\%%x
set ACTUAL_BATCH=!CURR_DIR!\callme.bat
echo !ACTUAL_BATCH!
ENDLOCAL & SET VAR=!ACTUAL_BATCH!
echo %VAR%
pause
)
pause
exit
main.bat 变体 3
@echo off
set PATH=C:\Temp
for /F %%x in ('dir /B/A:D %PATH%') do (
setlocal enabledelayedexpansion
set CURR_DIR=%PATH%\%%x
set ACTUAL_BATCH=!CURR_DIR!\callme.bat
echo !ACTUAL_BATCH!
REM source:
for /f "delims=" %%A in (""!ACTUAL_BATCH!"") do endlocal & set "VAR=%%~A"
echo %VAR%
call %VAR%
pause
)
pause
exit
所以我不知道该怎么办。有人有想法吗?
变体 1 的输出:
C:\Temp\callme.bat
not hidden message
C:\Temp\callme.bat
not hidden message
变体 2-3 的输出:
C:\Temp\callme.bat
ECHO is off.
C:\Temp\callme.bat
ECHO is off.
TL;DR
ENDLOCAL&set "varname=%sourcevarname%"
可能,其中 varname
是要设置的变量名,sourcevarname
是其值要分配给 varname
的变量 - 他们 CAN 是相同的名称,即使该语句在逻辑上显示为空 - 它从 setlocal/endlocal
块中导出变量。
要点:必须在一条物理线路上,必要时可以重复(即
ENDLOCAL&set "varname=%sourcevarname%"&set "varname2=%sourcevarname2%"
所以
ENDLOCAL&set "fred=%fred%"&set "bill=%george%"
完全有效,将 setlocal/endlocal 括号外的 fred
的值设置为其内部的最终值,将 bill
外部的值设置为 george
的最终值里面。
关于您的代码的一些要点:
永远不要使用
PATH
作为变量名,因为它会破坏用于搜索可执行文件的PATH
变量。使用扩展的
SET
语法set "varname=content"
来避免训练空间的问题。只需要使用
setlocal DisableDelayedExpansion
关闭延迟扩展模式即可
@echo off
setlocal EnableDelayedExpansion
set MY_PATH=C:\Temp
for /F %%x in ('dir /B/A:D %PATH%') do (
set "CURR_DIR=%MY_PATH%\%%x"
set "ACTUAL_BATCH=!CURR_DIR!\callme.bat"
call :execute ACTUAL_BATCH
pause
)
pause
exit /b
:execute ACTUAL_BATCH
set "batFile=!%~1!"
echo Calling !batFile!
setlocal DisableDelayedExpansion
call %batFile%
endlocal
exit /b