开发者

In cmd.exe, how can you get one variable to escape the setlocal command?

开发者 https://www.devze.com 2023-01-18 09:39 出处:网络
I frequently find myself using setlocal within cmd.exe to avoid polluting the environment variable space with temporary variables (and to ensure both command extensions and delayed expansion are activ

I frequently find myself using setlocal within cmd.exe to avoid polluting the environment variable space with temporary variables (and to ensure both command extensions and delayed expansion are active).

However, I'm at a loss on how to do this if I actually want one of those variables to be made available.

Consider the following code which gives you the final component of the current directory (so c:\pax\dir1 would give you dir1):

        @echo off
    :main
        setlocal enableextensions enabledelayedexpansion
        call :func
        echo.main_folder = %folder%
        endlocal
        goto :eof

    :func
        setlocal enableextensions enabledelayedexpansion
        set temp=%cd%
        set folder=
    :funcloop1
        if not "x%temp:~-1%"=="x\" (
            set folder=!temp:~-1!!folder!
            set temp=!temp:~1,-1!
            goto :funcloop1
        )
        echo.func_folder = %folder%
        endlocal
        goto :eof

When I run this, I get the output:

func_folder = dir1
main_folder =

and you can see that the %folder% variable does not survive the endlocal. However, if I leave off the setlocal/endlocal from the function, the temp varaible pollutes the namespace of main.

I know I can just use set temp= at the end of func and this will remove the environment variable but that doesn't cover the case where I'm already using that variable in the outside scope (it gets totally destr开发者_C百科oyed in that case).

Is there a way in cmd.exe to allow a select group of environment variables to propogate to the outside scope while still preventing others from affecting it? In other words, can you have both local variables and return variables?


Aside, please don't tell me there's a better way of getting the final path component. That is an example case only.

Actually, you can tell me a better way since it'd be nice to know but it won't be answering my specific question :-)


"The solution to this is to take advantage of the fact that the CMD shell evaluates variables on a line-by-line basis - so placing ENDLOCAL on the same line as the SET statement(s) gives the result we want:" source: ss64.com

So changing the endlocal of func: to this...

endlocal & set folder=%folder%

...will get you the behaviour you want.


For better reading and formatting, you can use parentheses.

call :func resultVar
echo(%resultVar%
goto :eof

:func 
setlocal
set var=2
(
  endlocal
  if "%1" NEQ "" set "%1=%var%"
  goto :eof
)

This works, because a command block will be expanded like a single line. The parser expands the first two phases (percent variables and escape characters) before executing the command block. The other phases are executed in time (Like delayed expansion, second expand phase by CALL, ...)


endlocal && set aaa=%aaa% && set bbb=%bbb% permanantly sets aaa and bbb outside of the setlocal and keeps this setting in the command prompt for another batch file to use (for exmaple, if the batch file containing the setlocal was called from another batch file the calling batch file will now have the new settings for aaa and bbb

Thanks to whoever explained about endlocal && set. I went through umpteen websites to get a resolution to this straight forward situation.

0

精彩评论

暂无评论...
验证码 换一张
取 消