for loop variable insanity

E

emrefan

I wanted to write a batch file for comparing files in the current
directory with those in another directory in terms of file size. And
the following is what I have so far:

@echo off
rem compare files in the current directory with those in another
directory
rem in terms of file size.
rem parameter to this batch ("the other directory") should include the
path separator
rem (backslash) if it is a proper directory spec rather than say
"<drive letter>:"

if "%1"=="" (
echo Usage %0 the-other-dir
goto :end
)

for %%f in (*.*) do (
set fn=%%f
echo %fn%
set fn2=%1%fn%
echo %fn%

for %%G in (%fn%) do set fz1=%%~zG
for %%H in (%fn2%) do set fz2=%%~zH
echo fz1=%fz1% fz2=%fz2%
)

:end

Now, every time I ran this batch file only things from the stupid to
the absolute insane happened. The results did not make any sense at
all. Sometimes the file sizes were insanely large, sometimes empty,
other times the filenames fetched were those from the last run and
were totally irrelevant to the recent invocation. I think the fact I
am assigning the for loop variable to another variable is making XP go
berserk because if I had the for loop modified to this below things
would appear normal.

for %%f in (*.*) do echo %%~zf

But of course that's not gonna get my job done. :(
 
P

Pegasus \(MVP\)

emrefan said:
I wanted to write a batch file for comparing files in the current
directory with those in another directory in terms of file size. And
the following is what I have so far:

@echo off
rem compare files in the current directory with those in another
directory
rem in terms of file size.
rem parameter to this batch ("the other directory") should include the
path separator
rem (backslash) if it is a proper directory spec rather than say
"<drive letter>:"

if "%1"=="" (
echo Usage %0 the-other-dir
goto :end
)

for %%f in (*.*) do (
set fn=%%f
echo %fn%
set fn2=%1%fn%
echo %fn%

for %%G in (%fn%) do set fz1=%%~zG
for %%H in (%fn2%) do set fz2=%%~zH
echo fz1=%fz1% fz2=%fz2%
)

:end

Now, every time I ran this batch file only things from the stupid to
the absolute insane happened. The results did not make any sense at
all. Sometimes the file sizes were insanely large, sometimes empty,
other times the filenames fetched were those from the last run and
were totally irrelevant to the recent invocation. I think the fact I
am assigning the for loop variable to another variable is making XP go
berserk because if I had the for loop modified to this below things
would appear normal.

for %%f in (*.*) do echo %%~zf

But of course that's not gonna get my job done. :(

Ah, the old environmental variable trap. You need to be aware that the code
interpreter will scan single statement of the form
for %%f in (*.*) do (
set fn=%%f
echo %fn%
set fn2=%1%fn%
echo %fn%
)
exactly once. The emphasis is on "single", because the two brackets cause
these five lines of code to be treated as one single line of code. At the
initial scan time, the variable "%fn%" is not defined, hence echoing it to
the screen will give you nothing!

To get around the problem, you must instruct the interpreter to scan
multiple-line statements one at a time, not as a block. Here is how it's
done. Note the exclamation marks!

@echo off
setlocal EnableDelayedExpansion

for %%f in (*.*) do (
set fn=%%f
echo !fn!
set fn2=%1%fn%
echo !fn!
)
echo %fn%
 
E

emrefan

Ah, the old environmental variable trap. You need to be aware that the code
interpreter will scan single statement of the form
for %%f in (*.*) do (
  set fn=%%f
  echo %fn%
  set fn2=%1%fn%
  echo %fn%
)
exactly once. The emphasis is on "single", because the two brackets cause
these five lines of code to be treated as one single line of code. At the
initial scan time, the variable "%fn%" is not defined, hence echoing it to
the screen will give you nothing!

To get around the problem, you must instruct the interpreter to scan
multiple-line statements one at a time, not as a block. Here is how it's
done. Note the exclamation marks!

@echo off
setlocal EnableDelayedExpansion

for %%f in (*.*) do (
  set fn=%%f
  echo !fn!
  set fn2=%1%fn%
  echo !fn!
)
echo %fn%- Hide quoted text -

Thanks for the patience with this newbie. It was kinda surprising to
me. I wish MS would make it easier for us in their newer software
(Vista?). It's counter-intuitive to say the least, very likely to
trap up people coming over from other shell environments.
 
P

Pegasus \(MVP\)

Ah, the old environmental variable trap. You need to be aware that the
code
interpreter will scan single statement of the form
for %%f in (*.*) do (
set fn=%%f
echo %fn%
set fn2=%1%fn%
echo %fn%
)
exactly once. The emphasis is on "single", because the two brackets cause
these five lines of code to be treated as one single line of code. At the
initial scan time, the variable "%fn%" is not defined, hence echoing it to
the screen will give you nothing!

To get around the problem, you must instruct the interpreter to scan
multiple-line statements one at a time, not as a block. Here is how it's
done. Note the exclamation marks!

@echo off
setlocal EnableDelayedExpansion

for %%f in (*.*) do (
set fn=%%f
echo !fn!
set fn2=%1%fn%
echo !fn!
)
echo %fn%- Hide quoted text -

Thanks for the patience with this newbie. It was kinda surprising to
me. I wish MS would make it easier for us in their newer software
(Vista?). It's counter-intuitive to say the least, very likely to
trap up people coming over from other shell environments.

======================

Intuitive? What's intuitive about code like this:
for %%G in (%fn%) do set fz1=%%~zG
for %%H in (%fn2%) do set fz2=%%~zH
echo fz1=%fz1% fz2=%fz2%
 
A

Anteaus

Thanks for the patience with this newbie. It was kinda surprising to
me. I wish MS would make it easier for us in their newer software
(Vista?). It's counter-intuitive to say the least, very likely to
trap up people coming over from other shell environments.

I take it you mean unix/bash, in which case there is really no equivalent in
Windows. I think you'll find that most people resort to scripting languages
for tasks like this. VBScript, KiXStart, AutoIt, etc. To perform your task in
AutoIt is relatively simple, as it includes directory-list commands.
Intuitive? What's intuitive about code like this:
for %%G in (%fn%) do set fz1=%%~zG
for %%H in (%fn2%) do set fz2=%%~zH
echo fz1=%fz1% fz2=%fz2%

Might even be a prizewinner <g>

http://en.wikipedia.org/wiki/Obfuscated_C_Contest
 
E

emrefan

Thanks for the patience with this newbie. It was kinda surprising to
me. I wish MS would make it easier for us in their newer software
(Vista?).  It's counter-intuitive to say the least, very likely to
trap up people coming over from other shell environments.

======================

Intuitive? What's intuitive about code like this:
for %%G in (%fn%) do set fz1=%%~zG
   for %%H in (%fn2%) do set fz2=%%~zH
   echo fz1=%fz1% fz2=%fz2%- Hide quoted text -

I admit it is far from intuitive. But I was forced to write it as such
because I think we cannot have the ~z expansion with non-loop non-
numeric variables? I cannot have, say, %~zSomeVarContainingMyFileName%
or can I?
 
P

Pegasus \(MVP\)

Thanks for the patience with this newbie. It was kinda surprising to
me. I wish MS would make it easier for us in their newer software
(Vista?). It's counter-intuitive to say the least, very likely to
trap up people coming over from other shell environments.

======================

Intuitive? What's intuitive about code like this:
for %%G in (%fn%) do set fz1=%%~zG
for %%H in (%fn2%) do set fz2=%%~zH
echo fz1=%fz1% fz2=%fz2%- Hide quoted text -

I admit it is far from intuitive. But I was forced to write it as such
because I think we cannot have the ~z expansion with non-loop non-
numeric variables? I cannot have, say, %~zSomeVarContainingMyFileName%
or can I?

===============

Yes, you can but it gets even less intuitive. I suggest you start by
describing your requirement in functional terms.
 
E

emrefan

I admit it is far from intuitive. But I was forced to write it as such
because I think we cannot have the ~z expansion with non-loop non-
numeric variables? I cannot have, say, %~zSomeVarContainingMyFileName%
or can I?

===============

Yes, you can but it gets even less intuitive. I suggest you start by
describing your requirement in functional terms.- ÁôÂóQ¤Þ¥Î¤å¦r -

By that yes you do mean I can write something like %~zSOME_VAR% and
get back the size of the file whose name is contained in variable
SOME_VAR? Well I just tested that and failed.

As for the functional spec, in my first post, I said "I wanted to
write a batch file for comparing files in the current
directory with those in another directory in terms of file size."
Does that qualify as a functional spec?
 
P

Pegasus \(MVP\)

I admit it is far from intuitive. But I was forced to write it as such
because I think we cannot have the ~z expansion with non-loop non-
numeric variables? I cannot have, say, %~zSomeVarContainingMyFileName%
or can I?

===============

Yes, you can but it gets even less intuitive. I suggest you start by
describing your requirement in functional terms.- ÁôÂóQ¤Þ¥Î¤å¦r -

By that yes you do mean I can write something like %~zSOME_VAR% and
get back the size of the file whose name is contained in variable
SOME_VAR? Well I just tested that and failed.

As for the functional spec, in my first post, I said "I wanted to
write a batch file for comparing files in the current
directory with those in another directory in terms of file size."
Does that qualify as a functional spec?

=====================

Yes, it does, and here is a solution that is almost intuitive.
@echo off
set source=d:\temp
set target=e:\Test Folder
for /F "delims=" %%a in ('dir /b "%source%\*.*"') do call :Sub %%a
goto :eof

:Sub
for %%b in ("%source%\%*") do set SSize=%%~zb
for %%b in ("%target%\%*") do set TSize=%%~zb
if %SSize%==%TSize% goto :eof
echo The size of "%1" in "%Source%" is not the same as in "%Target%".
 

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