Bizzaar Batch FOR Loop Issue

H

hjmiii

Can some one try this on another PC to tell me if I'm insane or just
headed towards insanity?
I wrote this fairly simple script to go through a dir of log files and
delete the old ones.
To test: make a directory and put a bunch of .LOG text files in it.
Run the following in a batch file (Change "C:\TEMP\LOGS" to your
directory):

SET olddate=200608
SET LOGROOT=C:\TEMP\LOGS
FOR %%i IN ("%LOGROOT%\*.LOG") DO (SET FileName=%%i
SET FTIME=%%~ti
SET fyyyy=%FTIME:~6,4%
SET fmm=%FTIME:~0,2%
IF /I %fyyyy%%fmm% LSS %olddate% DEL "%FileName%"
SET fyyyy=
SET fmm=
)

On the 1st run I get this error:
200606 was unexpected at this time.
C:\> IF /I LSS 200606 DEL ""

i.e. The variables aren't populating.
If you got this same error, keep the command prompt window open, and
change the script to this, save and rerun:

SET olddate=200608
SET LOGROOT=C:\TEMP\LOGS
FOR %%i IN ("%LOGROOT%\*.LOG") DO (SET FileName=%%i
SET FTIME=%%~ti
SET fyyyy=%FTIME:~6,4%
SET fmm=%FTIME:~0,2%
ECHO %fyyyy%
ECHO %fmm%
REM IF /I %fyyyy%%fmm% LSS %olddate% DEL "%FileName%"
REM SET fyyyy=
REM SET fmm=
)

Now for each file I get an output looking something like this:
SET FileName=C:\TEMP\LOGS\file1.LOG
SET FTIME=09/08/2006 12:07 PM
SET fyyyy=~6,4
SET fmm=~0,2
ECHO
ECHO
REM IF /I LSS 200608 DEL ""
REM SET fyyyy=
REM SET fmm=
)
ECHO is on.
ECHO is on.
Keep that CMD window open, there's more:
You may now think that the =%FTIME:~6,4% and =%FTIME:~0,2% are to
blame, but take notice that the %Filename% SETS, but still doesn't
appear in the REM'ed IF statement...the plot thickens.

Now just for fun add "ECHO %FileName%" after "ECHO %fmm%" and before
the REM lines.
Run the file again. I get this:
SET FileName=C:\TEMP\LOGS\file1.LOG
SET FTIME=09/08/2006 12:07 PM
SET fyyyy=2006
SET fmm=09
ECHO ~6,4
ECHO ~0,2
ECHO C:\TEMP\LOGS\file1.LOG
REM IF /I ~6,4~0,2 LSS 200608 DEL "C:\TEMP\LOGS\file1.LOG"
REM SET fyyyy=
REM SET fmm=
)
~6,4
~0,2
C:\TEMP\LOGS\file1.LOG

Let the head scratching begin. Now the SET statements have all the
correct data, but 2 of the ECHOs are wrong.
Now cut those REM lines to the clipboard, save, and run it again.
Here's my output:
SET FileName=C:\TEMP\LOGS\file1.LOG
SET FTIME=09/08/2006 12:07 PM
SET fyyyy=2006
SET fmm=09
ECHO 2006
ECHO 09
ECHO C:\TEMP\LOGS\file1.LOG
)
2006
09
C:\TEMP\LOGS\file1.LOG

Wha Wha Wha?! All the echos are returning the correct data even though
I essentially did nothing.
So now that it's working, paste back in those REM lines, remove the
REMs and remove the echos.
You are now back to the original script, and this is the output:
SET FileName=C:\TEMP\LOGS\file1.LOG
SET FTIME=09/08/2006 12:07 PM
SET fyyyy=2006
SET fmm=09
IF /I 200609 LSS 200608 DEL "C:\TEMP\LOGS\file1.LOG"
SET fyyyy=
SET fmm=
)

What should have happened in the first place! Anyone know what's going
on here? Can someone repro this?
 
P

Pegasus \(MVP\)

Can some one try this on another PC to tell me if I'm insane or just
headed towards insanity?
I wrote this fairly simple script to go through a dir of log files and
delete the old ones.
To test: make a directory and put a bunch of .LOG text files in it.
Run the following in a batch file (Change "C:\TEMP\LOGS" to your
directory):

SET olddate=200608
SET LOGROOT=C:\TEMP\LOGS
FOR %%i IN ("%LOGROOT%\*.LOG") DO (SET FileName=%%i
SET FTIME=%%~ti
SET fyyyy=%FTIME:~6,4%
SET fmm=%FTIME:~0,2%
IF /I %fyyyy%%fmm% LSS %olddate% DEL "%FileName%"
SET fyyyy=
SET fmm=
)

On the 1st run I get this error:
200606 was unexpected at this time.
C:\> IF /I LSS 200606 DEL ""

i.e. The variables aren't populating.
If you got this same error, keep the command prompt window open, and
change the script to this, save and rerun:

SET olddate=200608
SET LOGROOT=C:\TEMP\LOGS
FOR %%i IN ("%LOGROOT%\*.LOG") DO (SET FileName=%%i
SET FTIME=%%~ti
SET fyyyy=%FTIME:~6,4%
SET fmm=%FTIME:~0,2%
ECHO %fyyyy%
ECHO %fmm%
REM IF /I %fyyyy%%fmm% LSS %olddate% DEL "%FileName%"
REM SET fyyyy=
REM SET fmm=
)

Now for each file I get an output looking something like this:
SET FileName=C:\TEMP\LOGS\file1.LOG
SET FTIME=09/08/2006 12:07 PM
SET fyyyy=~6,4
SET fmm=~0,2
ECHO
ECHO
REM IF /I LSS 200608 DEL ""
REM SET fyyyy=
REM SET fmm=
)
ECHO is on.
ECHO is on.
Keep that CMD window open, there's more:
You may now think that the =%FTIME:~6,4% and =%FTIME:~0,2% are to
blame, but take notice that the %Filename% SETS, but still doesn't
appear in the REM'ed IF statement...the plot thickens.

Now just for fun add "ECHO %FileName%" after "ECHO %fmm%" and before
the REM lines.
Run the file again. I get this:
SET FileName=C:\TEMP\LOGS\file1.LOG
SET FTIME=09/08/2006 12:07 PM
SET fyyyy=2006
SET fmm=09
ECHO ~6,4
ECHO ~0,2
ECHO C:\TEMP\LOGS\file1.LOG
REM IF /I ~6,4~0,2 LSS 200608 DEL "C:\TEMP\LOGS\file1.LOG"
REM SET fyyyy=
REM SET fmm=
)
~6,4
~0,2
C:\TEMP\LOGS\file1.LOG

Let the head scratching begin. Now the SET statements have all the
correct data, but 2 of the ECHOs are wrong.
Now cut those REM lines to the clipboard, save, and run it again.
Here's my output:
SET FileName=C:\TEMP\LOGS\file1.LOG
SET FTIME=09/08/2006 12:07 PM
SET fyyyy=2006
SET fmm=09
ECHO 2006
ECHO 09
ECHO C:\TEMP\LOGS\file1.LOG
)
2006
09
C:\TEMP\LOGS\file1.LOG

Wha Wha Wha?! All the echos are returning the correct data even though
I essentially did nothing.
So now that it's working, paste back in those REM lines, remove the
REMs and remove the echos.
You are now back to the original script, and this is the output:
SET FileName=C:\TEMP\LOGS\file1.LOG
SET FTIME=09/08/2006 12:07 PM
SET fyyyy=2006
SET fmm=09
IF /I 200609 LSS 200608 DEL "C:\TEMP\LOGS\file1.LOG"
SET fyyyy=
SET fmm=
)

What should have happened in the first place! Anyone know what's going
on here? Can someone repro this?

This is an old and well-known trap. By default, each batch file
line is scanned exactly once for variable resolution. A "line" is
defined as a single line of code or a set of lines enclosed in
parenthesis. This means that your various variables inside the
multi-line statement do not assume the expected values.

Here is how to get around the issue:

@echo off
setlocal enabledelayedexpansion
SET olddate=200608
SET LOGROOT=C:\TEMP\LOGS
FOR %%i IN ("%LOGROOT%\*.LOG") DO (
SET FileName=%%i
SET FTIME=%%~ti
SET fyyyy=!FTIME:~6,4!
SET fmm=!FTIME:~0,2!
IF /I !fyyyy!!fmm! LSS !olddate! DEL "!FileName!"
SET fyyyy=
SET fmm=
)
endlocal

A far simpler way would be to use a third-party
utility such as xxcopy.exe:

@echo off
set limit=30
xxcopy /db%limit% /rs /yy /s c:\temp\logs\*.log c:\Deleted\
 
O

over

[Trimmed many lines - see original post if you are interested]
A far simpler way would be to use a third-party
utility such as xxcopy.exe:

@echo off
set limit=30
xxcopy /db%limit% /rs /yy /s c:\temp\logs\*.log c:\Deleted\

Or one named delage32: (author: Horst Schaeffer)
delage32 c:\temp\logs\*.log 30 /recurse
 
H

hjmiii

Pegasus said:
This is an old and well-known trap. By default, each batch file
line is scanned exactly once for variable resolution. A "line" is
defined as a single line of code or a set of lines enclosed in
parenthesis. This means that your various variables inside the
multi-line statement do not assume the expected values.

Here is how to get around the issue:

@echo off
setlocal enabledelayedexpansion
SET olddate=200608
SET LOGROOT=C:\TEMP\LOGS
FOR %%i IN ("%LOGROOT%\*.LOG") DO (
SET FileName=%%i
SET FTIME=%%~ti
SET fyyyy=!FTIME:~6,4!
SET fmm=!FTIME:~0,2!
IF /I !fyyyy!!fmm! LSS !olddate! DEL "!FileName!"
SET fyyyy=
SET fmm=
)
endlocal

Unfortunately this didn't fully work, though reading up on delayed
variable expansion helped shed a little light on it. The problem is
still with the nested IF not expanding correctly at runtime. When I run
the above script, and/or variations of it, all the files get deleted
because the !fyyyy!!fmm! isn't expanded correctly. Only enclosing the
!fyyyy!!fmm! in quotes finally solved it.

SETLOCAL ENABLEDELAYEDEXPANSION
FOR %%i IN "("%LOGROOT%\*.LOG") DO (
SET FTIME=%%~ti
IF /I "!FTIME:~6,4!!FTIME:~0,2!" LSS "%olddate%" (DEL "%%i")
)
ENDLOCAL
A far simpler way would be to use a third-party
utility such as xxcopy.exe:

@echo off
set limit=30
xxcopy /db%limit% /rs /yy /s c:\temp\logs\*.log c:\Deleted\

My choices were slim as I am working in a locked down environment. If I
can't do it with the shell commands at my disposal, then I'm looking at
months of red tape to get a single new exe in there.

This seems to be working though.
Thanks
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top