【问题标题】:Keep variable after endlocal in Batch在批处理中在 endlocal 之后保留变量
【发布时间】:2019-06-21 11:34:31
【问题描述】:

我有一个文件夹结构,例如 C:\Temp\,有很多文件夹和文件,每个文件夹中都有一个“callme.bat”。我想创建一个所谓的 main.bat,它在主窗口中一个接一个地调用 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: https://stackoverflow.com/questions/3262287/make-an-environment-variable-survive-endlocal
    for /f "delims=" %%A in (""!ACTUAL_BATCH!"") do endlocal & set "VAR=%%~A"
    echo %VAR%

    call %VAR%
    pause
)
pause
exit

所以我不知道该怎么办。有人有想法吗?

变体 1 的输出:

C:\Temp\1\callme.bat
 not hidden message
C:\Temp\2\callme.bat
 not hidden message

变体 2-3 的输出:

C:\Temp\1\callme.bat
ECHO is off.
C:\Temp\2\callme.bat
ECHO is off.

【问题讨论】:

  • 请不要重新定义%PATH%,它是一个非常重要的系统变量,请在您的每个.bat文件中更改其名称。
  • 你不需要使用延迟扩展甚至Set。单行脚本应该可以正常工作,@For /F "Delims=" %%A In ('Dir /B/AD "C:\Temp" 2^>NUL')Do @Call "%%~fA\callme.bat" 2>NUL,或者,@For /D %%A In ("C:\Temp\*")Do @Call "%%~fA\callme.bat" 2>NUL

标签: windows batch-file cmd delayedvariableexpansion


【解决方案1】:

关于你的代码的几点:

  1. 永远不要使用PATH 作为变量名,因为它会破坏PATH 用于搜索可执行文件的变量。

  2. 使用扩展的SET 语法set "varname=content" 来避免训练空间的问题。

  3. 您只需使用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

【讨论】:

    【解决方案2】:

    TL;DR

    ENDLOCAL&set "varname=%sourcevarname%"
    

    可能,其中varname 是要设置的变量名,sourcevarname 是要赋值给varname 的变量——它们可以同名,即使语句在逻辑上显示为空 - 它正在从 setlocal/endlocal 块中导出变量。

    关键点:必须在一条物理线上,必要时可以重复(即

     ENDLOCAL&set "varname=%sourcevarname%"&set "varname2=%sourcevarname2%"
    

    所以

     ENDLOCAL&set "fred=%fred%"&set "bill=%george%"
    

    完全有效,将 setlocal/endlocal 括号外的fred 的值设置为其内部的最终值,并将billoutside 的值设置为内部的george 的最终值。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-03-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-03
      • 1970-01-01
      • 2011-03-16
      • 2015-03-23
      相关资源
      最近更新 更多