Batch file: Pass file name to sub from FOR loop
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 ExampleFile1.txt
C:Batch File ExampleFIle2.txt
C:Batch File ExampleFile3.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 /F
flag 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?
batch-file
add a comment |
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 ExampleFile1.txt
C:Batch File ExampleFIle2.txt
C:Batch File ExampleFile3.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 /F
flag 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?
batch-file
add a comment |
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 ExampleFile1.txt
C:Batch File ExampleFIle2.txt
C:Batch File ExampleFile3.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 /F
flag 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?
batch-file
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 ExampleFile1.txt
C:Batch File ExampleFIle2.txt
C:Batch File ExampleFile3.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 /F
flag 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?
batch-file
batch-file
asked Nov 19 '18 at 15:49
Egalth
525317
525317
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
parameters are separated by spaces - so C:Batch File Examplefile.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
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 atfor /?
, you'll see that you are using thefor /f ... in ("string") ...
variant. This runs the loop once with just the value ofstring
parsed into the loop-variable(s). In your case, that single value isC:Batch File Example*.txt
which -- as explained above -- will pass justC:Batch
into%1
ofdoecho
.
– 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
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53378230%2fbatch-file-pass-file-name-to-sub-from-for-loop%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
parameters are separated by spaces - so C:Batch File Examplefile.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
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 atfor /?
, you'll see that you are using thefor /f ... in ("string") ...
variant. This runs the loop once with just the value ofstring
parsed into the loop-variable(s). In your case, that single value isC:Batch File Example*.txt
which -- as explained above -- will pass justC:Batch
into%1
ofdoecho
.
– 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
add a comment |
parameters are separated by spaces - so C:Batch File Examplefile.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
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 atfor /?
, you'll see that you are using thefor /f ... in ("string") ...
variant. This runs the loop once with just the value ofstring
parsed into the loop-variable(s). In your case, that single value isC:Batch File Example*.txt
which -- as explained above -- will pass justC:Batch
into%1
ofdoecho
.
– 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
add a comment |
parameters are separated by spaces - so C:Batch File Examplefile.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
parameters are separated by spaces - so C:Batch File Examplefile.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
answered Nov 19 '18 at 15:54
Stephan
34.7k43255
34.7k43255
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 atfor /?
, you'll see that you are using thefor /f ... in ("string") ...
variant. This runs the loop once with just the value ofstring
parsed into the loop-variable(s). In your case, that single value isC:Batch File Example*.txt
which -- as explained above -- will pass justC:Batch
into%1
ofdoecho
.
– 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
add a comment |
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 atfor /?
, you'll see that you are using thefor /f ... in ("string") ...
variant. This runs the loop once with just the value ofstring
parsed into the loop-variable(s). In your case, that single value isC:Batch File Example*.txt
which -- as explained above -- will pass justC:Batch
into%1
ofdoecho
.
– 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
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
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
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
@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
@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
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53378230%2fbatch-file-pass-file-name-to-sub-from-for-loop%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown