Delayed Expansion is Enabled but Variables are not expanding in FOR loop

Status
This thread has been Locked and is not open to further replies. Please start a New Thread if you're having a similar issue. View our Welcome Guide to learn how to use this site.

ttx336

Thread Starter
Joined
Nov 7, 2012
Messages
49
Code:
@echo off
SetLocal EnableDelayedExpansion

SET count=1 

FOR /f "tokens=*" %%G IN ('dir /b') DO (
	echo %count%:%%G
	set /a count+=1
	)
	
EndLocal
Just a simple example, but the variable stays at 1

Code:
@echo off
setlocal EnableDelayedExpansion 
:: count to 5 storing the results in a variable
set _tst=0
FOR /l %%G in (1,1,5) Do (echo [!_tst!] & set /a _tst+=1)
echo Total = !_tst!
This one works... why not the first one? I would much rather use the first method in a much larger script that I am working on...

Thx in advance, GB
 

Squashman

Retired Trusted Advisor
Joined
Apr 4, 2003
Messages
19,786
Well in your first batch file you are using % symbols to reference your variable expansion. In your 2nd batch file you are using ! symbol to reference your variable expansion. Delayed Expansion requires you to use the ! exclamation.
 

ttx336

Thread Starter
Joined
Nov 7, 2012
Messages
49
I sure am confused about when to use ! and when to use %, hopefully, I will get a better understanding of this. In previous attempts at this, when I have used the wrong one I got no output at all, but that could be due to the fact that, as I think about it, in this case, I had declared and loaded the variable with a 1.

One thing I noticed in the working model, the first output of !count! puts out, of course, 1 but also what looks like two spaces, could be just one space, but subsequent output has no spaces, only 2:file.txt etc.

Thanks for your help.

-Gary
 

foxidrive

Banned
Joined
Oct 20, 2012
Messages
793
Your second snippet works here.

!variable! can be used anywhere after a 'setlocal enabledelayedexpansion' is declared (and before an 'endlocal' if one of those is used).

%variable% can also be used - but only when it is already set before being used inside a loop with parentheses.

If you have random spaces then watch for trailing spaces when you set variables.
 

ttx336

Thread Starter
Joined
Nov 7, 2012
Messages
49
Your second snippet works here.

!variable! can be used anywhere after a 'setlocal enabledelayedexpansion' is declared (and before an 'endlocal' if one of those is used).

%variable% can also be used - but only when it is already set before being used inside a loop with parentheses.

If you have random spaces then watch for trailing spaces when you set variables.

Geez, I often say this, and I truly mean it in this case, there are some smart people out there... and you and Squashman are two of them. There was a trailing space and of course, eliminating it fixed the issue. Just for interest, I also tried adding the /a for math, with the trailing space intact and that also resolved the issue.

Code:
@Echo off
SetLocal EnableExtensions EnableDelayedExpansion
SetLocal EnableDelayedExpansion
cls

set indate=%1
set /a count=0

for /f "skip=4 tokens=1-7 delims=/ " %%i in ('dir /tw /a-d') do (
	
set /a count+=1

:Month	
	set _month=%%i
	set /a _month=100!_month! %% 100
	set /a _month=!_month! * 100

:Day	
	set _day=%%j
	set /a _day=100!_day! %% 100

:Year
	set _year=%%k
	set /a _year=!_year! * 10000

:Combined	
	set /a _fdate=!_year! + !_month! + !_day!
	
	if !indate! LSS !_fdate! (
		echo !count!: %%o is newer than !indate!
				)
	)
In this code, where I initialized indate, I had to use only one percent sign, but for the tokens, I had to use two... why is that? And why is it we must use %variable% or !variable!? Is that simply how the parser differentiates between variables, tokens and command parameters? Is my terminology even correct?


and btw, will you please ctitique my code and point out where I might have done better? The command line is just the command filename (of course) and a date in the YYYYMMDD format, ie C:\newer.cmd 20100809

The purpose of the code is to find and list files that are newer than the supplied date.
-GB
 

foxidrive

Banned
Joined
Oct 20, 2012
Messages
793
Another method is to use the %%~ta date/time variable but this is specific to Windows region settings.

The line that generates the date expects DD/MM/YYYY in the date format in this case. Remove the REM to see what format yours is in.

Code:
@echo off
SetLocal EnableDelayedExpansion
cls
set indate=%1

for /f "delims=" %%a in ('dir /b /tw /a-d') do (
rem echo "%%a" - "%%~ta"
set d=%%~ta
set d=%d:6,4%%d:0,2%%d:3,2%
if %indate% LSS !d! echo %%a is newer than %indate%
)
pause
You can also use Xcopy with the /D switch and supply a date - and using the /L switch makes it just list the filenames. That also takes the timestamp into account and is a more robust/simple way of comparing date/time.

In a forINdo command it uses two %% for the metavariables in batch files, but only one % from a command prompt.

A replaceable parameter from the command line only uses %1 %2 %3 etc and an environment variable is always designated by surrounding it with % or ! for delayed expansion.

There are other ways to solve this issue and the one you use is personal preference a lot of the time - but it's often useful to adapt techniques that don't rely on regional settings - if possible, sometimes it's not. Batch files can be kludgy that way. :)
 

ttx336

Thread Starter
Joined
Nov 7, 2012
Messages
49
Code:
@echo off
SetLocal EnableDelayedExpansion
cls
set indate=%1

for /f "delims=" %%a in ('dir /b /tw /a-d') do (
set d=%%~ta
set d=!d:~6,4!!d:~0,2!!d:~3,2!
if %indate% LSS !d! echo %%a is newer than %indate%
)
This is what I had to do in order to get it to run... I had to add the ~ tilde and change from the % to the !

from this:
set d=%d:6,4%%d:0,2%%d:3,2%

to this:
set d=!d:~6,4!!d:~0,2!!d:~3,2!
 

ttx336

Thread Starter
Joined
Nov 7, 2012
Messages
49
I am amazed at how much you tightened up that code! I am so very glad that I asked you to take a look at it.

Thank you so very much,
-Gary
 

foxidrive

Banned
Joined
Oct 20, 2012
Messages
793
XP didn't ship with forfiles.exe but it is available for free download from Microsoft.

Vista and later come with forfiles by default.
 
Status
This thread has been Locked and is not open to further replies. Please start a New Thread if you're having a similar issue. View our Welcome Guide to learn how to use this site.

Users Who Are Viewing This Thread (Users: 0, Guests: 1)

As Seen On
As Seen On...

Welcome to Tech Support Guy!

Are you looking for the solution to your computer problem? Join our site today to ask your question. This site is completely free -- paid for by advertisers and donations.

If you're not already familiar with forums, watch our Welcome Guide to get started.

Join over 807,865 other people just like you!

Latest posts

Members online

Top