Batch file: Pass file name to sub from FOR loop












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 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 /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?










share|improve this question



























    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 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 /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?










    share|improve this question

























      0












      0








      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 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 /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?










      share|improve this question













      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 /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?







      batch-file






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Nov 19 '18 at 15:49









      Egalth

      525317




      525317
























          1 Answer
          1






          active

          oldest

          votes


















          2














          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






          share|improve this answer





















          • 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













          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
          });


          }
          });














          draft saved

          draft discarded


















          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









          2














          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






          share|improve this answer





















          • 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


















          2














          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






          share|improve this answer





















          • 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
















          2












          2








          2






          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






          share|improve this answer












          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







          share|improve this answer












          share|improve this answer



          share|improve this answer










          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 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




















          • 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


















          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




















          draft saved

          draft discarded




















































          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.




          draft saved


          draft discarded














          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





















































          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







          Popular posts from this blog

          MongoDB - Not Authorized To Execute Command

          in spring boot 2.1 many test slices are not allowed anymore due to multiple @BootstrapWith

          How to fix TextFormField cause rebuild widget in Flutter