How to use Windows CMD pipe( | ) feature with CALL :Label command option?

will picture will · Nov 21, 2010 · Viewed 62.5k times · Source

I have a frustrating problem when I want to use the pipe(|) feature with the Window's CMD shell's CALL :Label option. I have a very small example (below): call-test.cmd and sample output.

The nub of the issue was/is to pipe the output of a CMD script to another program, for example the tee utility, or find command. For example:

    @call   :Label-02  param  | tee call-test.log

Which would start the current command file at the label Label-02 and pipe the output to tee. Unfortunately using the pipe character(|) on the line with "call :label" option gives an error:

Invalid attempt to call batch label outside of batch script.

Whereas, "call example.cmd | tee example.log", works just fine.

The other IO redirection > works OK. It is just the one case when "call :label pipe(|)" is used that fails. To me it just looks like a windows bug.

Does anyone have a workaround and/or know of an explanation?

Thanks, Will


  • call-test output

    c:\> call-test
        [start]
        label 03 :: p1
    Invalid attempt to call batch label outside of batch script.
    Invalid attempt to call batch label outside of batch script.
        [done]
    Press any key to continue . . .
    
  • call-test

    @echo off 
    @rem   call-test.cmd
    @rem  _________________________________________________
    @rem    Test :label call option for .cmd files.
    @rem
    @echo   ^  [start]
    @call   :Label-03  p1
    @call   :Label-02  second  | find " "
    @call   :Label-02  second  | tee call-test.log
    @goto   Done
    @rem  _________________________________________________
    :Label-01 
    @echo   ^  label 01 :: %1
    @goto Exit
    @rem  _________________________________________________
    :Label-02 
    @echo   ^  label 02 :: %1
    @goto Exit
    @rem  _________________________________________________
    :Label-03 
    @echo   ^  label 03 :: %1
    @goto Exit
    @rem  _________________________________________________
    :Done 
    @echo   ^  [done]
    @pause
    @rem  _________________________________________________
    :Exit 
    @exit /b
    

Answer

jeb picture jeb · Nov 21, 2010

The cause is, that a pipe starts both sides in a cmd context (both run parallel in one cmd-box), and each side is interpreted as a real command line argument, and on the cmd line labels aren't allowed.

But you can call your function, if you restart your batch.

if not "%1"=="" goto %1
@call "%~0" :Label-02  param  | tee call-test.log

EDIT: The complete sample

@echo off
if not "%~1"=="START" goto :normalStart
shift 
shift 
call %0 %1 %2 %3 %4 %5 %6 %7 %8
exit /b

:normalStart
rem   call-test.cmd
rem  _________________________________________________
rem    Test :label call option for .cmd files.
rem
echo   ^  [start]
rem call   :Label-03  p1
rem call   :Label-02  second  | find " "
call "%~dpf0" "START" :Label-02  second  |  tee call-test.log
goto   Done
rem  _________________________________________________
:Label-01 
echo   ^  label 01 :: %1
goto Exit
rem  _________________________________________________
:Label-02 
echo   ^  label 02 :: %1
goto Exit
rem  _________________________________________________
:Label-03 
echo   ^  label 03 :: %1
goto Exit
rem  _________________________________________________
:Done 
echo   ^  [done]
pause
rem  _________________________________________________
:Exit 
exit /b