【问题标题】:Windows Batch script to redirect stdout to stdin of an EXE we've just runWindows 批处理脚本将标准输出重定向到我们刚刚运行的 EXE 的标准输入
【发布时间】:2015-10-08 11:53:21
【问题描述】:

我知道在批处理脚本中运行 EXE 时的正常行为是批处理脚本在继续之前等待 EXE 退出,但是有没有办法让批处理脚本继续执行,但将其 stdout 重定向到EXE 的标准输入?

基本上我正在尝试实现这个巧妙的技巧或类似的东西......

@ECHO OFF
echo This is a windows batch script...
dir /p C:\

C:\cygwin\bash.exe <--- Do some magic here

echo This is a bash shell script...
ls -la /cygdrive/c/
exit

echo We're back to the windows batch script again
REM Note: being able to return to the batch script isn't important

关于如何实现这一目标的任何想法?谢谢。

【问题讨论】:

    标签: windows batch-file pipe


    【解决方案1】:

    这应该可行:

    @ECHO OFF
    echo This is a windows batch script...
    dir /p C:\
    
    (
    ECHO echo This is a bash shell script...
    ECHO ls -la /cygdrive/c/
    ECHO exit
    ) | C:\cygwin\bash.exe
    
    echo We're back to the windows batch script again
    

    编辑回复评论

    如果你不想在每个 bash 行中添加ECHO,你可以使用这个方法:

    @ECHO OFF
    echo This is a windows batch script...
    dir /p C:\
    
    rem Get the number of the first line in this file that start with "###"
    for /F "delims=:" %%a in ('findstr /N "^###" "%~F0"') do set "line=%%a" & goto break
    :break
    
    rem Pass from that line to end of this file to bash.exe
    more +%line% "%~F0" | C:\cygwin\bash.exe 
    
    echo We're back to the windows batch script again
    goto :EOF
    
    
    #################################################################
    # The remainder of this file is a bash script running in cygwin #
    #################################################################
    
    echo This is a bash script!!
    ls -la /cygdrive/c/
    

    编辑#2

    我借用了 SonicAtom 的方法并稍作修改以使其更简单。这里是:

    @ECHO OFF
    setlocal
    
    rem This is a magic trick to run the bottom half of this script as a bash script
    if not defined _restarted (
        set _restarted=true
        cmd.exe /Q /D < "%~F0"
        rem Put any cleanup commands here
        echo/
        echo Bash script finished
        pause
        exit /B
    )
    cls
    "C:\cygwin\bin\bash.exe"
    
    #################################################################
    # The remainder of this file is a bash script running in cygwin #
    #################################################################
    
    echo This is a bash script!!
    ls -la /cygdrive/c/
    

    【讨论】:

    • 啊,我们同时发布了一个答案! :) 这种方法是有道理的,但我不喜欢将ECHO 附加到每一行的开头。我的解决方案稍微复杂一些,但生成的代码更简洁。
    • ... 以及编辑#2。
    【解决方案2】:

    没有回复?

    嗯,我自己找到了答案:

    test.bat:

    @ECHO OFF
    
    rem This is a magic trick to run the bottom half of this script as a bash script
    if not exist _.bat (
        echo @ECHO OFF >_.bat
        echo cmd.exe -c ^< %~nx0 >>_.bat
        _.bat
        rem Put any cleanup commands here
        del _.bat
        echo.
        echo Bash script finished
        pause
        exit /B
    )
    cls
    "C:\cygwin\bin\bash.exe"
    
    #################################################################
    # The remainder of this file is a bash script running in cygwin #
    #################################################################
    
    echo This is a bash script!!
    ls -la /cygdrive/c/
    

    工作原理:

    文件以批处理脚本开始。它编写另一个(临时)批处理脚本,该脚本运行另一个 cmd.exe shell,将原始批处理文件作为标准输入定向到 cmd.exe。然后,原始批处理文件就像一个包含在键盘上键入的命令的文本文件。它运行 bash.exe,并继续为 bash 提供标准输入。唯一的缺点是@ECHO OFF 不会在调用 bash.exe 之前运行的批处理文件部分生效。这是因为似乎没有办法在 cmd.exe 中关闭键盘回显。

    【讨论】:

    • 恐怕你的方法不起作用,原因是:bash.exe结束执行后,批处理文件继续下一行,所以它在每个bash行中标记错误。
    • 好的。我查看了您的代码,我之前的评论是错误的。但是,您需要通过 CALL 命令执行第二个批处理文件:call _.bat;否则,控件返回到原始文件并且不会执行清理代码。 (这是多么复杂的方法啊!)
    • 其实我的方法确实有效,包括清理代码,我知道是因为我正在使用它。但我更喜欢你上面的第一个编辑答案,它更干净、更优雅!谢谢! :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多