Time for another fun foray into Windows batch scripts. Perhaps you've used the FOR /F command to loop through the contents of a file (for instance, perhaps some data that was redirected to a text file from a command). Grab a line, act on its values, and output some text and commands.
Let's set this up. First, we have a data file named SomeAccounts.txt:
Josh
Mary
Suzy
Amanda
Trisha
Ben
Then, we have ProcessAccounts.bat, which we want to just loop through the accounts in the text file, tell us what they are, and tell us the first letter of the account name (just to have something to do):
Except when you do this, you encounter a problem: All of the values from the FOR loop are the same! It's as if the for loop ran the proper number of times, but it just ran on the last record over and over again! See below:
My account, Ben, starts with B.
My account, Ben, starts with B.
My account, Ben, starts with B.
My account, Ben, starts with B.
My account, Ben, starts with B.
My account, Ben, starts with B.
What's actually happening is the FOR loop is indeed running over every line, and setting the variables as instructed, but the results of those variables being altered isn't echoed until the FOR loop is complete, so the last value of the variable is what displays. This wouldn't be a problem if you were just using your FOR parameter, in this case %%i, but any variables you set while in the FOR loop, like username, experience this "wait until you're out of the loop" phenomenon.
The fix is simple enough, if you know about it! But I've found the solution to be a bit elusive, which is the whole point of sharing it now.
The key is the setlocal EnableDelayedExpansion command. As explained at ss64.com, making this statement before your FOR loop will enable you to display variables as their value at the moment you're referencing them, or their "intermediate values" while in the middle of the FOR loop. In addition to calling the setlocal command, you then have to reference your variables with the exclamation point (!) rather than percent (%) to indicate that you want to use the intermediate value.
Your script will then look like this:
It will now happily act as desired, outputting these results:
My account, Josh, starts with J.
My account, Mary, starts with M.
My account, Suzy, starts with S.
My account, Amanda, starts with A.
My account, Trisha, starts with T.
My account, Ben, starts with B.