Link to home
Start Free TrialLog in
Avatar of ReneGe
ReneGeFlag for Canada

asked on

BATCH FILE: FOR /R

Hi there,

I must make the FOR /R command work inside the following batch file.

Please not that I need the FOR /R to be in the FOR /L as is.

@echo off
SETLOCAL enabledelayedexpansion
SET Dir1=C:\Batchfiles

FOR /L %%A IN (1,1,1) DO (
  FOR /R "!Dir%%A!" %%A IN (*.bat) do echo %%A
  )
PAUSE
EXIT


Thanks,
Rene
Avatar of Qlemo
Qlemo
Flag of Germany image

You've used %%A as var for both FORs. You need to use different loop vars:

@echo off
SETLOCAL enabledelayedexpansion
SET Dir1=C:\Batchfiles

FOR /L %%A IN (1,1,1) DO (
  FOR /R "!Dir%%A!" %%B IN (*.bat) do echo %%B
  )
PAUSE
EXIT /b

Further, don't use EXIT without /B in a batch file - it will close your cmd.exe, even if called manually.
Any reason why you are not echoing the dir? Doesn't it matter where the batch files are located?
Avatar of ReneGe

ASKER

Hey Q!

It still does not work.

Have any other ideas?

Cheers,
Rene
Avatar of ReneGe

ASKER

?? I do echo the dir:  ...do echo %%B

What do you mean?
"Still doesn't work" is kind of vague ...
Avatar of ReneGe

ASKER

Sorry for that...

I get no output at all, but it does not close my cmd.exe

Just as a reference:
With the following, I get the expexted output.

@echo off
FOR /L %%A IN (1,1,1) DO (
  FOR /R "C:\Batchfiles" %%B IN (*.bat) do echo %%B
  )
PAUSE
EXIT /b

Open in new window

Testing at the moment. FOR /R seems not to allow usuage of delayed expansion in the directory parameter.
Any chance you change from
  set Dir1=C:\Batchfiles
  set Dir2=C:\OtherFiles
to
  set Dirs="C:\Batchfiles" "C:\Otherfiles"
?
Background: Try the following in cmdline:

cmd /v:on
@set dir1=C:\Batchfiles
@for /R !dir1! %B in (*.bat) do @echo %B
@for /R %dir1% %B in (*.bat) do @echo %B
exit

Only the latter will succeed.
ASKER CERTIFIED SOLUTION
Avatar of Qlemo
Qlemo
Flag of Germany image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of ReneGe

ASKER

cmd /v:on
@set dir1=C:\Batchfiles
@for /R !dir1! %B in (*.bat) do @echo %B   =  NO OUTPUT
@for /R %dir1% %B in (*.bat) do @echo %B  =  EXPECTED OUTPUT
As I wrote. No delayed expansion after /R ...
Avatar of ReneGe

ASKER

Seems I'll have to use CALL here...

Thanks Q for all your help.

Cheers,
Rene
Avatar of Bill Prew
Bill Prew

Sorry, been away for the day with real work :-).

You can avoid the call with this approach, for what it's worth...

@echo off
SETLOCAL enabledelayedexpansion
SET Dir1=C:\BatchFiles
FOR /L %%A IN (1,1,1) DO (
  FOR /F "tokens=*" %%B IN ('dir /s /b "!Dir%%A!\*.pdf"') do echo %%B
)
PAUSE
EXIT

~bp
Avatar of ReneGe

ASKER

Quelmo,

Just to let you know that with your help, I corrected my script and it works like a charm.

Thanks a lot pal...

Cheers,
Rene

BIll,
that's right, with exception of that it should search for .bat, not .pdf ;-)
Avatar of ReneGe

ASKER

==> billprew
Than's what I used at first (...dir /s /b...), but it must pass through 150 000 files and it was just to long.

Thanks for contributing :-)

Cheers,
Rene
==> Q

Yes, had done that for some testing at my end to keep the hits low.

==> R

I wouldn't think there would be a huge performance difference, I'm going to run a few tests, but did you quantify the difference over the same set of files?  And the first run doesn't count since it will cache some stuff for the future runs.

~bp
Okay, I did a test with the attached code.  the DIR approach is actually faster than the FOR /R approach on my machine.

I did two runs, against different directories.  And each test did a loop of three iterations of timings.  Below is the results.  The 5 second run was the first time that directory tree was traversed, so either approach would have been slow that time, since none of the data was in memory.

[Thu 08/26/2010 19:37:09.13 c:\temp]dirtime
[1] FOR
140 milliseconds
[1] DIR
109 milliseconds
[2] FOR
140 milliseconds
[2] DIR
109 milliseconds

[Thu 08/26/2010 19:37:11.85 c:\temp]dirtime
[1] FOR
5.0 seconds
[1] DIR
109 milliseconds
[2] FOR
234 milliseconds
[2] DIR
109 milliseconds
[3] FOR
234 milliseconds
[3] DIR
156 milliseconds

~bp
@echo off
for /L %%A in (1,1,3) do (
  echo [%%A] FOR
  timer /nologo
  for /R "c:\_temp" %%B in ("*.bat") do rem
  timer /nologo /s
  echo [%%A] DIR
  timer /nologo
  for /R  %%B in ('dir /b /s "c:\_temp\*.bat"') do rem
  timer /nologo /s
)

Open in new window

Avatar of ReneGe

ASKER

==> bp

Yes I see a huge differance. However, since their may be a cash involved, I will rerun both and let you know.

==>Q
Extensions are not important here.  I just added it for better performance while testing. I use *.*

Cheers,
Rene
Rene,
You should consider to request for reopening the question, if this discussion leads to something.
BTW, the dir /s/b approach was what came first into my mind, but I wanted to stay as tight as possible on the original code.
Avatar of ReneGe

ASKER

==> bp

I just want to let you know that I closed this thread before you started to be involved.

So please feel free to stop contributing since I will not be able to give further points.

Where did you get this timer?

Thanks,
Rene
Avatar of ReneGe

ASKER

==> Q

How do I reopen the question?
Avatar of ReneGe

ASKER

Thanks Q
Thanks Modalot
Avatar of ReneGe

ASKER

I will now do the test between both options and come right back.
Avatar of ReneGe

ASKER

Here are my results.

[1] FOR
1 minute, 41 seconds
[1] DIR
16 milliseconds
[2] FOR
5.8 seconds
[2] DIR
16 milliseconds

@echo off
FOR /L %%A in (1,1,2) do (
  echo [%%A] FOR
  timer /nologo
  for /R "S:" %%B in (*.*) do rem
  timer /nologo /s
  echo [%%A] DIR
  timer /nologo
  for /R  %%B in ('dir /b /s "S:"') do rem
  timer /nologo /s
)

Open in new window

Looks like DIR is the way to go ;-).

~bp
Actually, you need to change your script, not quite right.

~bp
@echo off
FOR /L %%A in (1,1,2) do (
  echo [%%A] FOR
  timer /nologo
  for /R "S:\" %%B in (*.*) do rem
  timer /nologo /s
  echo [%%A] DIR
  timer /nologo
  for /R  %%B in ('dir /b /s "S:\*.*"') do rem
  timer /nologo /s
)

Open in new window

Avatar of ReneGe

ASKER

HERE BETTER...

[1] FOR
5.7 seconds
[1] DIR
2.9 seconds
[2] FOR
5.9 seconds
[2] DIR
15.3 seconds

@echo off
FOR /L %%A in (1,1,2) do (
  echo [%%A] FOR
  timer /nologo
  for /R "S:" %%B in (*.*) do rem
  timer /nologo /s
  echo [%%A] DIR
  timer /nologo
  PUSHD s:\
  for /R  %%B in ('dir /b /s') do rem
  POPD
  timer /nologo /s
)

Open in new window

Crud, I see I made a mistake earlier.  You want to do it this way:

@echo off
FOR /L %%A in (1,1,3) do (
  echo [%%A] FOR
  timer /nologo
  for /R "S:\" %%B in (*.*) do rem
  timer /nologo /s
  echo [%%A] DIR
  timer /nologo
  for /F "tokens=*" %%B in ('dir /b /s "s:\*.*"') do rem
  timer /nologo /s
)

~bp
So, now that I have the code correct (sorry guys), they seem to run in about the same time on my system.

~bp
Avatar of ReneGe

ASKER

It does not seem to like ...('dir /b /s "s:\*.*"')
I had to add "PUSHD S:" before
It should work as I provided, what error did you get?

~bp
Avatar of ReneGe

ASKER

It DIRs throuch the C drive
Avatar of ReneGe

ASKER

It DIRs through the C drive
How do you know that, since it doesn't display any file info?

~bp
Avatar of ReneGe

ASKER

I tested it with a smaller dir eching %%B , but I made a finger glitch.

You are right, your script works.

I will try it now...

I'll be back!
Avatar of ReneGe

ASKER

After 4 minutes, I'm still at:

[1] FOR
5.7 seconds
[1] DIR

I'm still at work. I'll go home and continue from there.
@echo off
FOR /L %%A in (1,1,1) do (
  echo [%%A] FOR
  timer /nologo
  for /R "S:\" %%B in (*.*) do rem
  timer /nologo /s
  echo [%%A] DIR
  timer /nologo
  for /F "tokens=*" %%B in ('dir /b /s "S:\*.*"') do rem
  timer /nologo /s
)

Open in new window

Avatar of ReneGe

ASKER

[1] FOR
5.7 seconds
[1] DIR
28 minutes, 32 seconds
I assumed s: is a network drive?

~bp
Avatar of ReneGe

ASKER

3 sata drives in RAID 0
So that's local storage.  Don't understand why your results could be so different than mine.  Can you post up the exact script you are using?

~bp
Avatar of ReneGe

ASKER

I just changed the script in order to get a better idea.

Here are the results.

Also, when I look to the properties of the folder, I get 149957 files

Now, I have to figure out why the file quantites are so different.

But anyway, not ennuf to justify the time difference.

[1] FOR
Files:144374
2 minutes, 25 seconds
************************
[1] DIR
Files:157695
29 minutes, 42 seconds
@echo off

SETLOCAL enabledelayedexpansion

SET ForNUM=0
SET DirNUM=0

FOR /L %%A in (1,1,1) do (
  echo [%%A] FOR
  timer /nologo
  for /R "S:\" %%B in (*.*) do SET /a ForNUM=!ForNUM! + 1
  ECHO Files:!ForNUM!
  timer /nologo /s
  echo ************************
  echo [%%A] DIR
  timer /nologo
  for /F "tokens=*" %%B in ('dir /b /s "S:\*.*"') do SET /a DirNUM=!DirNUM! + 1
  ECHO Files:!DirNUM!
  timer /nologo /s
)

Open in new window

As far as the file counts, try adding /a-d to the DIR command to see if that gets closer.

~bp
BTW, for incrementing it is better to use
    set /A ForNUM += 1
as it does not require variable expansion.
Avatar of ReneGe

ASKER

Thanks Q & bp

I'll change it now and try again.

I'll be back...
Avatar of ReneGe

ASKER

The discrepancy between DIR and number of files from Explorer properties is kind of resolved.

Anyway, it is now clear that FOR is much faster than DIR.

I am just concerned that, due to the difference between DIR and FOR in file qtee, if I use FOR /R, I might skip some important files, so this will also need to be resolved.  Have any ideas?


WITH DELAYED EXPANSION ON
[1] FOR
Files:144377
25.1 seconds
************************
[1] DIR
Files:149969
26 minutes, 46 seconds

Cheers,
Rene

@echo off

SETLOCAL enabledelayedexpansion

SET ForNUM=0
SET DirNUM=0
ECHO WITH DELAYED EXPANSION ON

FOR /L %%A in (1,1,1) do (
  echo [%%A] FOR
  timer /nologo
  for /R "S:\" %%B in (*.*) do SET /A ForNUM +=1
  ECHO Files:!ForNUM!
  timer /nologo /s
  echo ************************
  echo [%%A] DIR
  timer /nologo
  for /F "tokens=*" %%B in ('DIR /a-d /b /s "S:\*.*"') do SET /A DirNUM +=1
  ECHO Files:!DirNUM!
  timer /nologo /s
)

Open in new window

SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of ReneGe

ASKER

So, assuming that your USB drive is the E: drive, is it fair for me to assume that something went wrong in the script? Unless your HDs are extremly slow.

Rene
Nothing went wrong, I have 10 times the number of files on the C: drive.

~bp
Avatar of ReneGe

ASKER

lol

Your indicated file sizes all looks so much the same. I got caught in a visual paradigm and did not realized that there was an extra decimal.

I guess we concluded this thread. what do you think?

Cheers,
Rene
Yes, I suppose we've beat this to death.  I'm rather surprised at the terrible performance of DIR, but it is what it is I guess.

~bp
Avatar of ReneGe

ASKER

Now we know...

It was nice working with you on this...

Have fun,
Rene
But noone can explain that yet?! Sounds strange to me ... It should not be a big difference, if at all. The only explanation I have is that the dir output is collected as a whole first, then parsed thru the FOR (so a "big" temporary file needs to be created) , while the FOR /R is applied to folder after folder, giving the system some rest to settle down and balance the cache - maybe.
Avatar of ReneGe

ASKER

==>Q

I have the same feeling.

The explanation of the FOR /R command as per: http://ss64.com/nt/for_r.html

This command walks down the folder tree starting at [drive:]path, and executes the DO statement against each matching file.

Have fun,
Rene
Avatar of ReneGe

ASKER

==> Q
Do you also feel that we have concluded this thread?
Yes, but I cannot recommend how you should close ... The discussion alone and in its whole is worth the points, though the initial answer is still correct.

Anyways, both issues with FOR /R are recorded for my (yet to create) part 2 of DOS anomalies. Thanks, Bill, for the thorough analysis of the timing - I guess we all have learned something ;-).

Thinking over that, we (Bill and I) should give YOU points for asking this interesting question :).
Avatar of ReneGe

ASKER

Your help and friendship is ennuf.

Thanks for the thought though.

Again, it was nice working with you guys!

Thanks a lot for all your help.

Cheers,
Rene
Agree, fun and interesting thread, glad to have been a part of it.

(and I still may poke more at this if time allows at some point down the road...)

~bp
Avatar of ReneGe

ASKER

Guys, something is wrong, so I was unable to but my new thread in the Windows Batch zone.

I thought you may what to have a look at this one.

https://www.experts-exchange.com/questions/26439921/Batch-File-FOR-R-Copy-file-with-exclamation-point-in-the-name.html

Thanks for your help & cheers,
Rene