1.

Solve : Variable in FOR loop?

Answer»

Greetings. I am wanting to create a text file listing all the files in a DIRECTORY. A quick search on google provided myriad examples. The below for loop works fine. Note, I added the time stamp string in order to write the time stamp at the top of my file in my required format.

@ECHO OFF
::Create timestamp as string
SET Dt=%date:~10,4%%date:~4,2%%date:~7,2% %time%
SET str=%dt%
ECHO %str% >> c:\FileList.txt
::The below FOR loop is an exact copy of an example I found on google.
FOR /r "C:\Documents and Settings\Administrator\My Documents\My Pictures" %%X IN (*.jpg) DO (
ECHO %%X >> c:\FileList.txt
)

The above script works exactly as needed. My problem is that I want to introduce a variable within the FOR loop to hold the value of %%X. The reason is that I want to be able to manipulate it. The below is what I tried.

@ECHO OFF
:: Create timestamp as string
SETLOCAL ENABLEDELAYEDEXPANSION
SET Dt=%date:~10,4%%date:~4,2%%date:~7,2% %time%
SET str=%dt%
ECHO %str% >> c:\FileList.txt
FOR /r "C:\Documents and Settings\Administrator\My Documents\My Pictures" %%X IN (*.jpg) DO (
SET !var! = %%X
ECHO %var% >> c:\FileList.txt
)

The output of the file looks like this:
20110522 10:17:18.21
ECHO is off.
ECHO is off.
ECHO is off.
ECHO is off.
.....

I read a little bit about the SETLOCAL ENABLEDELAYEDEXPANSION option, but I'm not sure that I fully get it, as my limited experience is with VB. What I want to do is ECHO %var% instead of %%X, once again, because I want to be able to further manipulate it once I can get it working. I should also note I am not experienced with DOS code (or what ever it is called). I would greatly appreciate any suggestions or help. Thank you.

Greg

You need to focus on this area. Make a test batch with just this part of your work. By braking something into smaller parts, it is easier to see what happens.

Quote

FOR /r "C:\Documents and Settings\Administrator\My Documents\My Pictures" %%X IN (*.jpg) DO (
SET !var! = %%X
ECHO %var% >> c:\FileList.txt
)

Try to debug your test batch with more ECHO statements. For example, use a simple ECHO of the variable befog and after you change it. Surprise! Delayed expansion ?
A very "interesting" post from Geek.

gsnidow, due to the way the Windows NT family command interpreter (which is not "DOS", by the way) processes variable expansion in FOR structures, to set and expand variables within a loop, you need to use "delayed expansion". You set it up in a batch file by including this line somewhere before the loop

setlocal enabledelayedexpansion

The case doesn't matter - upper or lower or a mixture of the two, all are OK. Mostly it's OK to put it right at the start after the @echo off line that starts most scripts. If you leave it out then you can't use delayed expansion variables of the !var! type

Now, we come to how you use this feature within a loop, (in fact within any structure where multiple lines are enclosed in brackets)

You assign (set) the variable in the normal way, by using the set command followed immediately by an equals sign and then the variable value:

SET var=%%X

Note that there are no exclamation marks ("exclamation points") in the above line.

To read (expand) the variable within the loop you treat it like a normal variable, but with the difference that you use exclamation marks (!) and not percent signs (%):

echo !var! >> c:\FileList.txt

You can do all the usual variable processing stuff with such a variable.

Note also that once the loop has finished (after the closing bracket of the loop) you can still access the variable but you use percent signs as normal. In the script you showed above, after the loop has finished, %var% will contain the last value that !var! held. This might be useful sometimes if you want to know the last item in a list or sequence.

A point - using double colons :: as comment markers is unofficial, undocumented and unsupported, and will in certain situations (within a loop for example) break a script. Use REM or Rem or rem or ReM instead.

Another point - writing ALL the commands in UPPER CASE is not compulsory.





Thank you so much Geek and Salmon for the very helpful points. I have made it easier on myself by creating c:\test, and putting only 3 files in it, Test1.txt..Test3.txt. At Geek's suggestion, I have been working on only the problem part, which, with my new test folder, boils down to...

FOR /r "C:\test" %X IN (*.txt) DO SET var = %X

Note I am not trying to do this in a batch file now, because I want to see what is happening in the cmd window. As expected, the output of this line is...

C:\...>SET var = C:\test\Test1.txt
C:\...>SET var = C:\test\Test2.txt
C:\...>SET var = C:\test\Test3.txt

This RESULT seems to me to imply that for each iteration of the loop, it is correctly assigning the value of the current file name to the var variable. I then tried this...

FOR /r "C:\test" %X IN (*.txt) DO SET var = %X ECHO %var

My thought was that since, based on my assumption above, the variable is being correctly set, the next step would be to ECHO it. However, this is not the case, as the output is now...

C:\...>SET var = C:\test\Test1.txt ECHO %var
C:\...>SET var = C:\test\Test2.txt ECHO %var
C:\...>SET var = C:\test\Test3.txt ECHO %var

It seems that it is only appending "ECHO %var" to the variable value, along with the file name of the current iteration. I am thinking it must be possible to carry out multiple actions in the DO part of the loop, but I can't seem to get it. One question to the delayed execution: I am having trouble understanding why it is necessary if, based on my first results, it seems to be correctly assigning the variable value without it.

@Salmon - I'm going to continue to mess with it before I simply copy and paste your line of code, so I will probably have some more questions later. As for the all caps, I'm a SQL guy, and my practice is to always put key words in all caps, because it makes the code easier to read.

Once again, I very much appreciate both of your helping me as I muddle through being a newbie at this. Thank you so much.

Greg





Quote
FOR /r "C:\test" %X IN (*.txt) DO SET var = %X ECHO %var

1. You can't do this.

2. Variables have a percent sign before and after so %var won't work.

3.

Quote
As expected, the output of this line is...

C:\...>SET var = C:\test\Test1.txt
C:\...>SET var = C:\test\Test2.txt
C:\...>SET var = C:\test\Test3.txt

It was just echoing "set var = " (which is wrong; lose those spaces) and expanding %X. The variable %var% was not being set correctly. Trust me.

Quote
It was just echoing "set var = " (which is wrong; lose those spaces) and expanding %X. The variable %var% was not being set correctly. Trust me.

Ah ha, those darned spaces. All seems to be good now, so I very much appreciate the help. One last question, how do I know when to use '%' and when to use '!' to wrap my variables? Thanks again.

GregQuote from: gsnidow on May 23, 2011, 05:51:16 AM
how do I know when to use '%' and when to use '!' to wrap my variables? Thanks again.

You use % all the time except when you want to expand a variable, in a loop or other parenthetical structure (e.g. a long form IF), which you have previously set in that structure.


@Salmon - I apologize if this is a newbie question, but I don't know what you mean by expanding a variable. I read some stuff on google, but most of it was dealing with posters having issues with expanding their variables in various languages. Could you possibly put it in laymen terms? Thanks.

GregWhole waiting or Salmon Trout, here is some more reading.
http://www.robvanderwoude.com/variableexpansion.phpQuote from: gsnidow on May 23, 2011, 08:14:40 PM
I don't know what you mean by expanding a variable. Could you possibly put it in laymen terms?


OK here GOES...

You create a variable with the SET command, and when you use it in a statement, it gets "expanded" by the command interpreter cmd.exe.

set animal=cat

The command interpreter reserves some memory space for a variable called "animal" and stores the THREE characters 'cat' in that space.

later you have

echo %animal%

When the command interpreter processes this line it identifies the variable because of the percent signs and looks up the value of "animal" in its list of variables. It finds 'cat' so it replaces %animal% with cat and executes

echo cat

This process of replacing a variable's name with the value it holds is called "expansion".




Thanks for the help and explanation guys. That is a great article, and it does not seem so strange now. I very much appreciate you taking time out of your busy days to consider and respond to my questions.

Greg


Discussion

No Comment Found