windowsbatch-filecmdmethod-callforfiles

Why can't we use a CALL :label command in the FORFILES script?


This snippet of code

forfiles /P %pathname% /M *.log /c "cmd /c echo @file"

will happily list out a bunch of files.

We could replace the ECHO with RENAME or MOVE or many other combinations of internal commands: the exception being a CALL to a label name.

For instance replacing the ECHO above as follows:

forfiles /P %pathname% /M *.log /c "cmd /c CALL :listit @file"
 : :
 : :
exit /b

:listit
echo %1
exit /b

Which I would have hoped would have the same output gives an error message, typically

Invalid attempt to call batch label outside of batch script.

This behaviour is not something that Microsoft's documentation remarks on, and since the alternatives are perfectly adequate, I've not gone looking to make it work.

But I am interested in the Well, why not?!, and so I'm posing the Question

Why can't we use a CALL :label command in the FORFILES script?

Thank you.


Solution

  • As @Stephan commented already, it can't uses labels, because it's executed in a command line context.

    In most of the cases you can use the simpler FOR command.

    But in cases where you need forfiles and labels, this can be solved with a simple trick.

    1. At the begin of your batch file you need the line FOR /F ... goto :%%L.
    2. And when calling the label it has to be enclosed forfiles ... call %~d0\:<myLabel>:\..\%~pn0
    @echo off
    FOR /F "tokens=3 delims=:" %%L in ("%~0") DO goto :%%L
    
    ...
    forfiles /P %pathname% /M *.log /c "cmd /c CALL %~d0\:listit:\..\%~pn0 @file"
    ...
    
    :listit
    echo %1
    exit /b
    

    A good advice from aschipfl:
    To add some more stability (against spaces in the path/filename) you can enclose the call destination into quotes call 0x22%~d0\:listit:\..\%~pn00x22 @file.

    This is a special syntax only in forfiles, where 0xHH is the hexadecimal code for the character 0x22=".