I am trying to use setlocal enabledelayedexpansion
and cd
together in a batch script, which seems to not persist changes back to shell.
The
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
>
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 set
ted after that.
(sorry for hijacking your answer, but that's also too big for a comment)
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.
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