SETLOCAL ENABLEDELAYEDEXPANSION causes CD and PUSHD to not persist

前端 未结 4 444
春和景丽
春和景丽 2021-01-18 08:41

I am trying to use setlocal enabledelayedexpansion and cd together in a batch script, which seems to not persist changes back to shell.

The

相关标签:
4条回答
  • 2021-01-18 08:49

    The problem is that setlocal causes any current directory changes to be local to the batch file.

    See setlocal /?:

    Begins localization of environment changes in a batch file. Environment changes made after SETLOCAL has been issued are local to the batch file. ENDLOCAL must be issued to restore the previous settings. When the end of a batch script is reached, an implied ENDLOCAL is executed for any outstanding SETLOCAL commands issued by that batch script.

    Current directory is included in "environment changes".

    Try this, notice that it echoes C:\ for %CD% inside the batch, but the current directory is still reset when the batch exits.

    [11:42:00.17] C:\temp
    > cat test.bat
    @echo off
    setlocal enabledelayedexpansion
    cd ..
    echo %CD%
    [11:42:19.38] C:\temp
    > test.bat
    C:\
    
    [11:42:23.00] C:\temp
    >
    
    0 讨论(0)
  • 2021-01-18 08:49

    Saving a string in registry across endlocal. Tested on win7 cmd (skip=2, may differ with different versions of reg.exe)

    :: What: stash string in registry from cmd line, across endlocal barrier
    :: PS. I added %RANDOM% to Windows-NT and Win95 command.com and still using it.
    @echo off
    
    set key="HKCU\Volatile Environment"
    set keyname=stash%RANDOM%
    set keytype=REG_SZ
    
    setlocal ENABLEDELAYEDEXPANSION
    
    ::== Save string
    set data_stash=Hello-%DATE%-%TIME%
    echo Saving=%data_stash% in key=%keyname%
    reg add %key% /v %keyname% /t %keytype% /d "%data_stash%" /f
    
    endlocal
    
    ::== Read string
    echo reg query %key% /v %keyname%
    for /f "tokens=2* skip=2" %%a in ('reg query %key% /v %keyname%') do (
      set data_unstashed=%%b
    )
    echo Read data_unstashed=%data_unstashed% 
    
    ::== Delete stash
    reg delete %key%  /v %keyname% /f  
    

    Edit Stephan another way to save variables beyond endlocal:

    @echo off
    set var1=hello
    set var2=world
    setlocal 
    echo previous: %var1%, %var2%
    set var1=HELLO
    set var2=WORLD
    echo inside:   %var1%, %var2%
    endlocal & set "var1=%var1%" & set "var2=%var2%" 
    echo after:    %var1%, %var2%
    

    The trick is that due to the parsing the variables are expanded before endlocal is effective, but setted after that.
    (sorry for hijacking your answer, but that's also too big for a comment)

    0 讨论(0)
  • 2021-01-18 08:58

    Blorgbeard provided an explanation as to why CD issued after SETLOCAL does not persist after ENDLOCAL (could be explicit or implicit).

    Here is an interesting work-around. The PUSHD stack is independent of the environment that is saved/restored by SETLOCAL/ENDLOCAL. So the following simple sequence will preserve the directory change:

    @echo off
    setlocal
    cd somePath
    pushd .
    endlocal
    popd
    

    Not very useful if somePath is constant - you could just as easily issue the CD after the ENDLOCAL. But it can be very useful if somePath is dynamic.

    0 讨论(0)
  • 2021-01-18 09:03

    Here is proof that it works - start the batch file in any folder above the root.

    @echo off
    setlocal enabledelayedexpansion
    echo "%cd%"
    cd ..
    echo "%cd%"
    pause
    
    0 讨论(0)
提交回复
热议问题