SETLOCAL ENABLEDELAYEDEXPANSION导致CD和PUSHD不能持续存在

时间:2014-10-07 22:13:11

标签: batch-file windows-scripting

我正在尝试在批处理脚本中一起使用setlocal enabledelayedexpansioncd,这似乎不会将更改保留回shell。

我需要setlocal enabledelayedexpansion的原因是我需要在脚本运行时动态扩展脚本中的变量。

考虑以下示例批处理文件:

a.bat
================================
setlocal enabledelayedexpansion
cd ..

上述批处理文件未按预期迁移到上一个目录!

检查this

4 个答案:

答案 0 :(得分:7)

Blorgbeard提供了一个解释,说明为什么在SETLOCAL之后发布的CD在ENDLOCAL之后不会持久存在(可能是明确的或隐含的)。

这是一个有趣的解决方法。 PUSHD堆栈与SETLOCAL / ENDLOCAL保存/恢复的环境无关。因此,以下简单序列将保留目录更改:

@echo off
setlocal
cd somePath
pushd .
endlocal
popd

如果somePath不变,则不太有用 - 您可以在ENDLOCAL之后轻松发行CD。但如果somePath是动态的,那么它会非常有用。

答案 1 :(得分:4)

问题是setlocal导致当前目录更改对批处理文件是本地的。

请参阅setlocal /?

  

在批处理文件中开始环境更改的本地化。 <强>环境   发出SETLOCAL后所做的更改是批处理文件的本地更改。   必须发出ENDLOCAL才能恢复以前的设置。什么时候结束   到达批处理脚本时,将执行任何隐含的ENDLOCAL   由该批处理脚本发出的未完成的SETLOCAL命令。

当前目录包含在“环境变化”中。

尝试此操作,请注意它在批处理中为C:\回显%CD%,但当批处理退出时,当前目录仍会重置。

[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
>

答案 2 :(得分:0)

以下证明它有效 - 在根目录上的任何文件夹中启动批处理文件。

@echo off
setlocal enabledelayedexpansion
echo "%cd%"
cd ..
echo "%cd%"
pause

答案 3 :(得分:0)

在endlocal中的注册表中保存字符串。在win7 cmd上测试(skip = 2,可能因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  

编辑Stephan 另一种保存变量超出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%

诀窍在于,由于解析,变量在 endlocal生效之前已扩展,但在之后set
(对不起劫持你的答案,但这对评论来说也太大了)