0

This question is about the correct syntax for passing file name arguments to a subroutine in a batch file. Feels like this question should have been asked before, but I can't seem to find the right answer. Assume there are three text files in a folder called C:\Batch File Example. The following code (partly borrowed from this answer) will output the file names:

@echo off
SETLOCAL Enableextensions

ECHO Line before FOR
FOR /R "C:\Batch File Example\" %%i in (*.txt) DO ECHO %%i
ECHO Line after FOR & PAUSE>NUL

Output:

Line before FOR
C:\Batch File Example\File1.txt
C:\Batch File Example\FIle2.txt
C:\Batch File Example\File3.txt
Line after FOR

Now, I want to produce the same output by using a subroutine instead, like this:

@echo off
SETLOCAL Enableextensions

ECHO Line before FOR
FOR /R "C:\Batch File Example\" %%i in (*.txt) DO CALL :doecho %%i
ECHO Line after FOR & PAUSE>NUL
GOTO :EOF

:doecho
SET VAR=%1
ECHO VAR is %VAR%
EXIT /b

But this gives the following output, where the result is truncated:

Line before FOR
VAR is C:\Batch
VAR is C:\Batch
VAR is C:\Batch
Line after FOR

The result above suggests that whitespace is treated as a delimiter and that %1 only contains C:\Batch, so I tried using the following for loop instead, with the /Fflag and a comma delimiter to suppress the whitespace:

FOR /F "delims=," %%i IN ("C:\Batch File Example\*.txt") DO CALL :doecho %%i

However, this also returns the truncated result, with the only difference that there is only one iteration instead of three.

I've tried using enhanced variable substitionts like %~I instead of %%i and %1, but I'm stuck. So what am I missing?

Egalth
  • 962
  • 9
  • 22

1 Answers1

2

parameters are separated by spaces - so C:\Batch File Example\file.txt are three parameters (more, if the filename also contains spaces).

Either use %* ("all parameters") instead of %1 or use quotes: ... CALL :doecho "%%I", then it's a single (quoted) parameter. If you need to remove the quotes in your subroutine, use %~1

Stephan
  • 53,940
  • 10
  • 58
  • 91
  • Great, both alternatives work like a charm. Not very intuitive... Btw, any insight into why the for loop with the `/F` flag only iterated once? – Egalth Nov 19 '18 at 16:06
  • 1
    @Egalth If you look at `for /?`, you'll see that you are using the `for /f ... in ("string") ...` variant. This runs the loop _once_ with just the value of `string` parsed into the loop-variable(s). In your case, that single value is `C:\Batch File Example\*.txt` which -- as explained above -- will pass just `C:\Batch` into `%1` of `doecho`. – TripeHound Nov 19 '18 at 16:21
  • @TripeHound, good point, thanks! @Stephan's solution will indeed work with the following syntax, without any command extension: `FOR %%i IN ("C:\Batch File Example\*.txt") DO CALL :doecho "%%i"`. – Egalth Nov 19 '18 at 16:35