Variable Expansion Within a DOS FOR Loop

Ah, the DOS FOR loop. Had I known about you earlier in life, I would probably have a day or two back. But atlas, it wasn't until recently that we met.
My first tech blog post and I'm talking about a FOR loop in DOS? Well, I figured I should start at the beginning, and for me, that's DOS.
In my current contract, I do a lot of automation in DOS. And any kind of automation is made easier with loops. Enter the FOR command. I have to admit that I didn’t know anything about the FOR command under DOS before I started this job and had to analyze someone else’s batch files. But now that I have, I’m a better scripter for knowing it.
One of the more troublesome things that I’ve dealt with is trying to set environment variables and using them all within the FOR loop. It just doesn’t work. But if you stop to think about it, it makes sense as to why it doesn’t work. Look at the example below.
Script
SET check=0
FOR %%A IN (1 2) DO (
SET check=%%A
ECHO Mic check %check%.
)
Output
Mic check 0.
Mic check 0.
Because all of the environment variables within the DO () are expanded only when the FOR command is reached, not for every iteration of the loop, their values are static. So in this example when the FOR command is reached, the expansion of check to its current value of 0 takes place and then the looping begins. It would look something this.
SET check=0
FOR %%A IN (1 2) DO (
SET check=%A
ECHO Mic check 0.
)
Note how check is expanded to 0 inside the DO ().
So, how do you deal with this limitation? There are 2 ways. The first is by using the CALL command to move the logic out of the DO () and to a different part of your script. Below is a modified version of the script that behaves in the wanted manner.
Script
SET check=0
FOR %%A IN (1 2) DO (
CALL :MicCheck %%A
)
GOTO :eof
:MicCheck
SET check=%1
ECHO Mic check %check%.
GOTO :eof
Output
Mic check 1.
Mic check 2.
The second way of handling this is by turning on delayed variable expansion. I don’t like this method as much because unless you have it enabled by default, which it’s not as of the time of this posting, scripts don’t work out-the-door. For them to work on first run, you have to play with the SETLOCAL and ENDLOCAL commands inside your batch file. I’ve run into odd scope behaviors in the past doing this, so I prefer the CALL method shown above.
Script
SET check=0
SETLOCAL ENABLEDELAYEDEXPANSION
FOR %%A IN (1 2) DO (
SET check=%%A
ECHO Mic check %check%.
)
ENDLOCAL
Output
Mic check 1.
Mic check 2.
Now, this is a simple example, but I’m sure you can see how you can expand this to do what you’d like.
Happy scripting!


