Page 1 of 1

Limitation in for /r command

Posted: 16 May 2014 22:02
by foxidrive
I've run some simple tests and found the
for /r command cannot accept a variable for the "c:\path" portion in for /r "c:\path" %%a in (*) do when it is within a loop.

Consider this example: you must have folders with a tree of files inside them, in the current directory.
Nothing is echoed.


Code: Select all

@echo off

for /d %%a in (*) do (
     for /r "%%a" %%b in (*) do echo "%%b" 
  )


I've tried it with an environment variable that is set before the loop starts, and that works ok
but using delayed expansion is not a solution either as it doesn't change the result: see below

Code: Select all

@echo off
setlocal enabledelayedexpansion

for /d %%a in (*) do (
set "folder=%cd%"
     for /r "!folder!" %%b in (*) do echo "%%b" 
  )



The issue doesn't really need parentheses as this fails too.

Code: Select all

@echo off

for /d %%a in (*) do   for /r "%%a" %%b in (*) do echo "%%b" 
 



So the expected syntax would have to change for this to work.

foxi

Re: Limitation in for /r command

Posted: 16 May 2014 23:05
by dbenham
I find that behavior unfortunate, but not surprising.

Without the quotes around %%a it yields a syntax error. With the quotes it yields a screwy result without any recursion.

I believe both behaviors result from the order of patch parsing. The FOR and IF statements get special option parsing that takes place before both delayed expansion and FOR variable expansion. The special parser needs the values at parse time, so you can't use delayed expansion or FOR variables.

Similar syntax failures happen with:

Code: Select all

@echo off
setlocal enableDelayedExpansion
set option=/i
if !option! a==A echo OK

set "option=delims="
for /f "!option!" %%A in ("1 2") do echo %%A
Use of FOR variables for the options fails the same way.

There is a simple enough work-around for the FOR /R problem:

Code: Select all

@echo off
setlocal
for /d %%a in (*) do (
  pushd "%%a"
  set pushd=1
  for /r %%b in (*) do (
    if defined pushd (
      popd
      set "pushd="
    )
    do echo "%%b"
  )
  if defined pushd ( 
    popd
    set "pushd="
  )
)


Dave Benham

Re: Limitation in for /r command

Posted: 17 May 2014 00:05
by foxidrive
Thanks for the confirmation and testing, Dave.

This generates an interesting error message - unbalanced quotes:

Code: Select all

@echo off
setlocal enableDelayedExpansion

set "option=delims="
for /f "!option!" %%A in ("1 2") do echo %%A
pause


!option!" was unexpected at this time.


I also worked around it like so for the original request.

Code: Select all

@echo off
for /d %%a in (*) do (
  pushd "%%a"
    for /r %%b in (*.pdf *.txt) do echo "%%b"
  popd
)

Re: Limitation in for /r command

Posted: 17 May 2014 05:28
by dbenham
foxidrive wrote:I also worked around it like so for the original request.

Code: Select all

@echo off
for /d %%a in (*) do (
  pushd "%%a"
    for /r %%b in (*.pdf *.txt) do echo "%%b"
  popd
)

Sure, if you don't care what the current directory is within your inner loop, (which of course is true with the ECHO statement). I added the extra complexity so that it functions exactly like a normal FOR /R except without the late expansion issue, assuming PUSHD variable is not already being used.


Dave Benham

Re: Limitation in for /r command

Posted: 04 Feb 2022 12:57
by aschipfl
foxidrive wrote:
17 May 2014 00:05
This generates an interesting error message - unbalanced quotes:

Code: Select all

@echo off
setlocal enableDelayedExpansion

set "option=delims="
for /f "!option!" %%A in ("1 2") do echo %%A
pause
!option!" was unexpected at this time.
The error message is the same when delayed expansion is disabled.
This proves that FOR /F receives the string !option! literally, which is of course no valid option string.

Re: Limitation in for /r command

Posted: 04 Feb 2022 18:32
by Eureka!
I ran into a similar issue here
Using that workaround here leads to:

Code: Select all

@echo off&setlocal

   for /d %%a in (*) do call :DEEPER "%%a"
goto :EOF


:DEEPER
   for /r %1 %%b in (*) do echo "%%b"  
goto :EOF