如何在CALL:Label命令选项中使用Windows CMD管道(|)功能?

wil*_*ill 18 cmd pipe batch-file call

当我想在Window的CMD shell的CALL:Label选项中使用管道(|)功能时,我遇到了一个令人沮丧的问题.我有一个非常小的例子(下面):call-test .cmd和示例输出.

该问题的核心是将CMD脚本的输出传递给另一个程序,例如tee实用程序或find命令.例如:

    @call   :Label-02  param  | tee call-test.log
Run Code Online (Sandbox Code Playgroud)

这将在标签Label-02处启动当前命令文件并将输出传递给tee.不幸的是,使用"call:label"选项行上的管道符号(|)会出错:

Invalid attempt to call batch label outside of batch script.
Run Code Online (Sandbox Code Playgroud)

然而," 调用example.cmd | tee example.log",工作得很好.

其他IO重定向>工作正常.只是在使用" call:label pipe(|) "失败的情况下.对我来说,它看起来像一个Windows bug.

有没有人有解决方法和/或知道解释?

谢谢,威尔


  • 呼叫测试输出

    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 . . .
    
    Run Code Online (Sandbox Code Playgroud)
  • 呼叫测试

    @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
    
    Run Code Online (Sandbox Code Playgroud)

jeb*_*jeb 14

原因是,管道在cmd上下文中开始(在一个cmd框中并行运行),并且每一侧都被解释为真正的命令行参数,并且不允许在cmd行标签上.

但是,如果重新启动批次,则可以调用您的函数.

if not "%1"=="" goto %1
@call "%~0" :Label-02  param  | tee call-test.log
Run Code Online (Sandbox Code Playgroud)

编辑:完整的样本

@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
Run Code Online (Sandbox Code Playgroud)


cha*_*lup 1

明显的解决方法是将调用的输出重定向到临时文件,将其用作 find/tee 的输入,然后删除文件:

@call :Label-02 second > tmp
tee call-test.log < tmp
delete tmp
Run Code Online (Sandbox Code Playgroud)