#1 15 Apr 2020 12:22

rdhoore108
New Member
Registered: 15 Apr 2020
Posts: 3

endlocal

Hi,

I have an interesting observation that first puzzled me, but then became quite logical. Maybe something about it could be added to the existing page about endlocal...

Imagine a script that sets a bunch of variables whose names are starting with an underscore, and upon endlocal we want to preserve those variables. Can easily be done with a FOR loop, right?

@echo off
setlocal EnableDelayedExpansion
FOR /F %%I IN ('WMIC path win32_localtime get Year^,Month^,Day^,DayOfWeek^,Hour^,Minute^,Second /format:list^|FINDSTR "="') DO SET _%%I
REM imagine more lines here that actively use delayed expansion
set _& endlocal &FOR /F %%I IN ('set _') DO SET %%I

This is the output:

_Day=15
_DayOfWeek=3
_Hour=11
_Minute=51
_Month=4
_Second=42
_Year=2020
Environment variabele _ not defined

What the heck? So, the first "set _" nicely shows all variables, but the very same "set _" in the FOR loop throws that strange error?

Even when we replace that last line as follows for debugging purposes, the same output and error appears:

set _& endlocal &set _

Why does the first "set _" work, and the second fail?

The answer is actually simple: when the second `set _` is executed, endlocal was already executed. So no more variables starting with an underscore exist.

It's a different thing to do something like

endlocal &set _Day=%_Day%

because in this case, %_Day% is expanded BEFORE these commands get executed.

To only workaround to this problem I found, is using a temporary file instead. Would anyone know of a niftier solution?

@echo off
setlocal EnableDelayedExpansion
FOR /F %%I IN ('WMIC path win32_localtime get Year^,Month^,Day^,DayOfWeek^,Hour^,Minute^,Second /format:list^|FINDSTR "="') DO SET _%%I
REM imagine more lines here that actively use delayed expansion
set _>%TEMP%\%~n0.tmp
endlocal& FOR /F %%I IN (%TEMP%\%~n0.tmp) DO SET %%I
del %TEMP%\%~n0.tmp

Offline

#2 15 Apr 2020 13:32

bluesxman
Member
From: UK
Registered: 29 Dec 2006
Posts: 1,118

Re: endlocal

In my experience all solutions to this problem are hacky, and have their own advantages and pitfalls.  If you have a bunch of variables you don't necessarily have all the names for, this is probably the least-worst solution.

One small change I would make though, would be

SET "%%I"

in case any of your variables contain special characters.


cmd | *sh | ruby | chef

Offline

#3 15 Apr 2020 16:50

rdhoore108
New Member
Registered: 15 Apr 2020
Posts: 3

Re: endlocal

Thanks for the thoughtful reply! Would have been great if delayed expansion could be enabled and disabled in some other way. I could never figure out why someone at Microsoft decided to do it through "setlocal".

Good point about the quotes. Thank you.

Offline

#4 15 Apr 2020 18:30

Simon Sheppard
Super Administrator
Registered: 27 Aug 2005
Posts: 1,082
Website

Re: endlocal

If you are using a temporary file, then you can just put the endlocal on a separate line for clarity.

Offline

#5 16 Apr 2020 09:46

bluesxman
Member
From: UK
Registered: 29 Dec 2006
Posts: 1,118

Re: endlocal

rdhoore108 wrote:

Would have been great if delayed expansion could be enabled and disabled in some other way.

You can enable delayed expansion for all CMD sessions by default via a registry hack, but that might have unintended results in scripts that aren't expecting it to be enabled by default.

You can also enable it at run time with a command line switch, similar caveats to above apply.

Details of both are here:

https://ss64.com/nt/delayedexpansion.html


cmd | *sh | ruby | chef

Offline

#6 18 Apr 2020 14:50

rdhoore108
New Member
Registered: 15 Apr 2020
Posts: 3

Re: endlocal

Good point, @Simon. There is no advantage to having it on the same line.

@Bluesxman, yes, I think you actually hit the nail on the head as to why someone@MS decided to do it through setlocal: because then calling scripts will not be affected if we change it. (I never liked the idea to change the default behavior, never did that and never will.)

Thank you both!

Offline

Board footer

Powered by FluxBB