Solved

BATCH FILE: FOR /R

Posted on 2010-08-26
63
742 Views
Last Modified: 2012-05-10
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
0
Comment
Question by:ReneGe
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 31
  • 17
  • 14
63 Comments
 
LVL 70

Expert Comment

by:Qlemo
ID: 33537296
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.
0
 
LVL 70

Expert Comment

by:Qlemo
ID: 33537309
Any reason why you are not echoing the dir? Doesn't it matter where the batch files are located?
0
 
LVL 10

Author Comment

by:ReneGe
ID: 33537330
Hey Q!

It still does not work.

Have any other ideas?

Cheers,
Rene
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 10

Author Comment

by:ReneGe
ID: 33537336
?? I do echo the dir:  ...do echo %%B

What do you mean?
0
 
LVL 70

Expert Comment

by:Qlemo
ID: 33537352
"Still doesn't work" is kind of vague ...
0
 
LVL 10

Author Comment

by:ReneGe
ID: 33537397
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

0
 
LVL 70

Expert Comment

by:Qlemo
ID: 33537420
Testing at the moment. FOR /R seems not to allow usuage of delayed expansion in the directory parameter.
0
 
LVL 70

Expert Comment

by:Qlemo
ID: 33537448
Any chance you change from
  set Dir1=C:\Batchfiles
  set Dir2=C:\OtherFiles
to
  set Dirs="C:\Batchfiles" "C:\Otherfiles"
?
0
 
LVL 70

Expert Comment

by:Qlemo
ID: 33537466
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.
0
 
LVL 70

Accepted Solution

by:
Qlemo earned 250 total points
ID: 33537543
A workaround, maintaining your dir variables, is
@echo off

SETLOCAL enabledelayedexpansion
SET Dir1=Batchfiles

FOR /L %%A IN (1,1,1) DO call :search !Dir%%A!
pause
exit /b

:search
FOR /R "%1" %%B IN (*.bat) do echo %%B
EXIT /b

Open in new window

0
 
LVL 10

Author Comment

by:ReneGe
ID: 33537549
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
0
 
LVL 70

Expert Comment

by:Qlemo
ID: 33537642
As I wrote. No delayed expansion after /R ...
0
 
LVL 10

Author Comment

by:ReneGe
ID: 33537660
Seems I'll have to use CALL here...

Thanks Q for all your help.

Cheers,
Rene
0
 
LVL 54

Expert Comment

by:Bill Prew
ID: 33537766
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
0
 
LVL 10

Author Comment

by:ReneGe
ID: 33537768
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

0
 
LVL 70

Expert Comment

by:Qlemo
ID: 33537779
BIll,
that's right, with exception of that it should search for .bat, not .pdf ;-)
0
 
LVL 10

Author Comment

by:ReneGe
ID: 33537815
==> 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
0
 
LVL 54

Expert Comment

by:Bill Prew
ID: 33537825
==> 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
0
 
LVL 54

Expert Comment

by:Bill Prew
ID: 33537907
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

0
 
LVL 10

Author Comment

by:ReneGe
ID: 33537924
==> 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
0
 
LVL 70

Expert Comment

by:Qlemo
ID: 33537938
Rene,
You should consider to request for reopening the question, if this discussion leads to something.
0
 
LVL 70

Expert Comment

by:Qlemo
ID: 33537943
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.
0
 
LVL 10

Author Comment

by:ReneGe
ID: 33537944
==> 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
0
 
LVL 10

Author Comment

by:ReneGe
ID: 33537950
==> Q

How do I reopen the question?
0
 
LVL 54

Expert Comment

by:Bill Prew
ID: 33537973
0
 
LVL 10

Author Comment

by:ReneGe
ID: 33537982
Thanks Q
Thanks Modalot
0
 
LVL 10

Author Comment

by:ReneGe
ID: 33537993
I will now do the test between both options and come right back.
0
 
LVL 10

Author Comment

by:ReneGe
ID: 33538036
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

0
 
LVL 54

Expert Comment

by:Bill Prew
ID: 33538061
Looks like DIR is the way to go ;-).

~bp
0
 
LVL 54

Expert Comment

by:Bill Prew
ID: 33538067
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

0
 
LVL 10

Author Comment

by:ReneGe
ID: 33538130
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

0
 
LVL 54

Expert Comment

by:Bill Prew
ID: 33538165
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
0
 
LVL 54

Expert Comment

by:Bill Prew
ID: 33538191
So, now that I have the code correct (sorry guys), they seem to run in about the same time on my system.

~bp
0
 
LVL 10

Author Comment

by:ReneGe
ID: 33538194
It does not seem to like ...('dir /b /s "s:\*.*"')
I had to add "PUSHD S:" before
0
 
LVL 54

Expert Comment

by:Bill Prew
ID: 33538205
It should work as I provided, what error did you get?

~bp
0
 
LVL 10

Author Comment

by:ReneGe
ID: 33538212
It DIRs throuch the C drive
0
 
LVL 10

Author Comment

by:ReneGe
ID: 33538213
It DIRs through the C drive
0
 
LVL 54

Expert Comment

by:Bill Prew
ID: 33538236
How do you know that, since it doesn't display any file info?

~bp
0
 
LVL 10

Author Comment

by:ReneGe
ID: 33538261
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!
0
 
LVL 10

Author Comment

by:ReneGe
ID: 33538297
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

0
 
LVL 10

Author Comment

by:ReneGe
ID: 33538566
[1] FOR
5.7 seconds
[1] DIR
28 minutes, 32 seconds
0
 
LVL 54

Expert Comment

by:Bill Prew
ID: 33538598
I assumed s: is a network drive?

~bp
0
 
LVL 10

Author Comment

by:ReneGe
ID: 33538713
3 sata drives in RAID 0
0
 
LVL 54

Expert Comment

by:Bill Prew
ID: 33540831
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
0
 
LVL 10

Author Comment

by:ReneGe
ID: 33541039
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

0
 
LVL 54

Expert Comment

by:Bill Prew
ID: 33541105
As far as the file counts, try adding /a-d to the DIR command to see if that gets closer.

~bp
0
 
LVL 70

Expert Comment

by:Qlemo
ID: 33541338
BTW, for incrementing it is better to use
    set /A ForNUM += 1
as it does not require variable expansion.
0
 
LVL 10

Author Comment

by:ReneGe
ID: 33541507
Thanks Q & bp

I'll change it now and try again.

I'll be back...
0
 
LVL 10

Author Comment

by:ReneGe
ID: 33541909
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

0
 
LVL 54

Assisted Solution

by:Bill Prew
Bill Prew earned 250 total points
ID: 33544785
Okay, it seems to be dramatically impacted by the number of files involved.  For whatever reason, the FOR approach clobbers the DIR approach when the number of files gets 'large'.  Here are the results of three tests I did against different drives on my system, the last of which was an external USB device.

~bp
Dir = [g:\], [*.*]
  LOOP = [1]
    FOR = Files:[124], Time:[78 milliseconds]
    DIR = Files:[124], Time:[62 milliseconds]
  LOOP = [2]
    FOR = Files:[124], Time:[46 milliseconds]
    DIR = Files:[124], Time:[78 milliseconds]
  LOOP = [3]
    FOR = Files:[124], Time:[78 milliseconds]
    DIR = Files:[124], Time:[62 milliseconds]

Dir = [c:\], [*.*]
  LOOP = [1]
    FOR = Files:[224248], Time:[1 minute, 57 seconds]
    DIR = Files:[230341], Time:[22 minutes, 46 seconds]
  LOOP = [2]
    FOR = Files:[224276], Time:[35.1 seconds]
    DIR = Files:[230370], Time:[22 minutes, 32 seconds]
  LOOP = [3]
    FOR = Files:[224300], Time:[37.1 seconds]
    DIR = Files:[230398], Time:[22 minutes, 7 seconds]

Dir = [e:\], [*.*]
  LOOP = [1]
    FOR = Files:[22877], Time:[36.4 seconds]
    DIR = Files:[27406], Time:[19.2 seconds]
  LOOP = [2]
    FOR = Files:[22877], Time:[1.6 seconds]
    DIR = Files:[27406], Time:[19.4 seconds]
  LOOP = [3]
    FOR = Files:[22877], Time:[1.5 seconds]
    DIR = Files:[27406], Time:[19.3 seconds]

Open in new window

0
 
LVL 10

Author Comment

by:ReneGe
ID: 33545496
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
0
 
LVL 54

Expert Comment

by:Bill Prew
ID: 33545664
Nothing went wrong, I have 10 times the number of files on the C: drive.

~bp
0
 
LVL 10

Author Comment

by:ReneGe
ID: 33545864
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
0
 
LVL 54

Expert Comment

by:Bill Prew
ID: 33545886
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
0
 
LVL 10

Author Comment

by:ReneGe
ID: 33545941
Now we know...

It was nice working with you on this...

Have fun,
Rene
0
 
LVL 70

Expert Comment

by:Qlemo
ID: 33545979
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.
0
 
LVL 10

Author Comment

by:ReneGe
ID: 33546058
==>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
0
 
LVL 10

Author Comment

by:ReneGe
ID: 33546169
==> Q
Do you also feel that we have concluded this thread?
0
 
LVL 70

Expert Comment

by:Qlemo
ID: 33546426
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 :).
0
 
LVL 10

Author Comment

by:ReneGe
ID: 33546469
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
0
 
LVL 54

Expert Comment

by:Bill Prew
ID: 33546861
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
0
 
LVL 10

Author Comment

by:ReneGe
ID: 33563266
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.

http://www.experts-exchange.com/OS/Microsoft_Operating_Systems/MS_DOS/Q_26439921.html

Thanks for your help & cheers,
Rene
0

Featured Post

Is Your DevOps Pipeline Leaking?

Is your CI/CD pipeline a hodge-podge of randomly connected tools? You’ve likely got a tool to fix one problem & then a different tool to fix another, resulting in a cluster of tools with overlapping functionality. Learn how to optimize your pipeline with Gartner's recommendations

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This is about my first experience with programming Arduino.
In this post we will learn how to make Android Gesture Tutorial and give different functionality whenever a user Touch or Scroll android screen.

752 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question