• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 814
  • Last Modified:

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
0
ReneGe
Asked:
ReneGe
  • 31
  • 17
  • 14
2 Solutions
 
QlemoBatchelor, Developer and EE Topic AdvisorCommented:
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
 
QlemoBatchelor, Developer and EE Topic AdvisorCommented:
Any reason why you are not echoing the dir? Doesn't it matter where the batch files are located?
0
 
ReneGeAuthor Commented:
Hey Q!

It still does not work.

Have any other ideas?

Cheers,
Rene
0
What Kind of Coding Program is Right for You?

There are many ways to learn to code these days. From coding bootcamps like Flatiron School to online courses to totally free beginner resources. The best way to learn to code depends on many factors, but the most important one is you. See what course is best for you.

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

What do you mean?
0
 
QlemoBatchelor, Developer and EE Topic AdvisorCommented:
"Still doesn't work" is kind of vague ...
0
 
ReneGeAuthor Commented:
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
 
QlemoBatchelor, Developer and EE Topic AdvisorCommented:
Testing at the moment. FOR /R seems not to allow usuage of delayed expansion in the directory parameter.
0
 
QlemoBatchelor, Developer and EE Topic AdvisorCommented:
Any chance you change from
  set Dir1=C:\Batchfiles
  set Dir2=C:\OtherFiles
to
  set Dirs="C:\Batchfiles" "C:\Otherfiles"
?
0
 
QlemoBatchelor, Developer and EE Topic AdvisorCommented:
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
 
QlemoBatchelor, Developer and EE Topic AdvisorCommented:
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
 
ReneGeAuthor Commented:
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
 
QlemoBatchelor, Developer and EE Topic AdvisorCommented:
As I wrote. No delayed expansion after /R ...
0
 
ReneGeAuthor Commented:
Seems I'll have to use CALL here...

Thanks Q for all your help.

Cheers,
Rene
0
 
Bill PrewCommented:
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
 
ReneGeAuthor Commented:
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
 
QlemoBatchelor, Developer and EE Topic AdvisorCommented:
BIll,
that's right, with exception of that it should search for .bat, not .pdf ;-)
0
 
ReneGeAuthor Commented:
==> 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
 
Bill PrewCommented:
==> 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
 
Bill PrewCommented:
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
 
ReneGeAuthor Commented:
==> 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
 
QlemoBatchelor, Developer and EE Topic AdvisorCommented:
Rene,
You should consider to request for reopening the question, if this discussion leads to something.
0
 
QlemoBatchelor, Developer and EE Topic AdvisorCommented:
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
 
ReneGeAuthor Commented:
==> 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
 
ReneGeAuthor Commented:
==> Q

How do I reopen the question?
0
 
Bill PrewCommented:
0
 
ReneGeAuthor Commented:
Thanks Q
Thanks Modalot
0
 
ReneGeAuthor Commented:
I will now do the test between both options and come right back.
0
 
ReneGeAuthor Commented:
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
 
Bill PrewCommented:
Looks like DIR is the way to go ;-).

~bp
0
 
Bill PrewCommented:
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
 
ReneGeAuthor Commented:
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
 
Bill PrewCommented:
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
 
Bill PrewCommented:
So, now that I have the code correct (sorry guys), they seem to run in about the same time on my system.

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

~bp
0
 
ReneGeAuthor Commented:
It DIRs throuch the C drive
0
 
ReneGeAuthor Commented:
It DIRs through the C drive
0
 
Bill PrewCommented:
How do you know that, since it doesn't display any file info?

~bp
0
 
ReneGeAuthor Commented:
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
 
ReneGeAuthor Commented:
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
 
ReneGeAuthor Commented:
[1] FOR
5.7 seconds
[1] DIR
28 minutes, 32 seconds
0
 
Bill PrewCommented:
I assumed s: is a network drive?

~bp
0
 
ReneGeAuthor Commented:
3 sata drives in RAID 0
0
 
Bill PrewCommented:
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
 
ReneGeAuthor Commented:
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
 
Bill PrewCommented:
As far as the file counts, try adding /a-d to the DIR command to see if that gets closer.

~bp
0
 
QlemoBatchelor, Developer and EE Topic AdvisorCommented:
BTW, for incrementing it is better to use
    set /A ForNUM += 1
as it does not require variable expansion.
0
 
ReneGeAuthor Commented:
Thanks Q & bp

I'll change it now and try again.

I'll be back...
0
 
ReneGeAuthor Commented:
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
 
Bill PrewCommented:
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
 
ReneGeAuthor Commented:
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
 
Bill PrewCommented:
Nothing went wrong, I have 10 times the number of files on the C: drive.

~bp
0
 
ReneGeAuthor Commented:
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
 
Bill PrewCommented:
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
 
ReneGeAuthor Commented:
Now we know...

It was nice working with you on this...

Have fun,
Rene
0
 
QlemoBatchelor, Developer and EE Topic AdvisorCommented:
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
 
ReneGeAuthor Commented:
==>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
 
ReneGeAuthor Commented:
==> Q
Do you also feel that we have concluded this thread?
0
 
QlemoBatchelor, Developer and EE Topic AdvisorCommented:
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
 
ReneGeAuthor Commented:
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
 
Bill PrewCommented:
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
 
ReneGeAuthor Commented:
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
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

What Kind of Coding Program is Right for You?

There are many ways to learn to code these days. From coding bootcamps like Flatiron School to online courses to totally free beginner resources. The best way to learn to code depends on many factors, but the most important one is you. See what course is best for you.

  • 31
  • 17
  • 14
Tackle projects and never again get stuck behind a technical roadblock.
Join Now