捕获通过管道传输到批处理文件的真正 STDIN

Posted

技术标签:

【中文标题】捕获通过管道传输到批处理文件的真正 STDIN【英文标题】:Capturing true STDIN piped to a batch file 【发布时间】:2019-09-05 15:10:39 【问题描述】:

我想在一些其他命令之后从批处理文件中访问 STDIN。我知道 .BAT 文件中的第一个命令接收 STDIN,但我想先运行一些其他命令然后捕获 STDIN。我还希望它可以与流式 STDIN 一起使用,即在开始时将 STDIN 捕获到文件中是不可接受的(请参阅下面的解决方法)。

现在,我知道CON 是代表 STDIN 的“文件”,TYPE CON 将输出(回显)STDIN。这在批处理文件中似乎根本不起作用。实际上,它似乎不代表 STDIN,而是代表用户/主机通过键盘输入。

test.bat

TYPE CON > output.txt

测试运行:

C:>TYPE myfile.txt | test.bat

预期结果:myfile.txt 被复制到 output.txt

实际结果:批处理等待用户输入(忽略通过管道传输的内容)并将用户在键盘上输入的输入写入output.txt

解决方法

作为一种解决方法:以下test.bat 有效,但不支持流式输入(例如来自tail 命令):

findstr "^" STDIN.txt
:: I can now run some other commands
:: And finally access my STDIN via STDIN.txt
TYPE STDIN.txt | AWK /e/ > output.txt

更新:背景故事: 我有一个简洁的 CMD,它使用 powershell 下载(通过 HTTP)任意 .ps1 脚本(就像包管理器一样)并即时执行它。如果我调用REMEXEC.bat mymodule foo bar,它会使用参数foobar 加载并执行mymodule.ps1

这对于除管道、流式输入之外的所有场景都非常有效。使用findstr "^" 适用于管道输入,但不适用于开放流。使用AWK /.*/ 作为我的 BAT 的第一行可以让我获得流式输入,但只会将问题推到后面。

最终我想要一个看起来像这样的something.bat(伪代码):

downloadPSModule( "http://myrepo.com/modules/%1.ps1" )
STDIN | executePSModule %2 %3 %4

第 22 个问题是 downloadPSModule 发生在 executePSModule 之前,因此无法访问 STDIN(为 BAT 的第一行保留的特权)。

【问题讨论】:

你看到这个answer了吗?还有这个one? 我认为如果您提供具体任务,包括实际的可执行文件、命令和代码,我们会更容易为您提供帮助。 是的,我得到了@Squashman 的信息,似乎没有办法访问 STDIN(不是 CON)。 @Compo,我添加了一些背景故事。 实际结果:批处理等待用户输入(忽略通过管道传输的内容)并将用户在键盘上输入的输入写入 output.txt。 是的,没错,而且你告诉把你输入的东西放在一个文件中。当您完成输入文件时,按 Ctrl + Z 告诉它。 【参考方案1】:

如果您需要从控制台检索输入或从标准输入流中隔离读取以不消耗管道数据,我会尝试使用类似的东西直接从控制台读取

@echo off
    setlocal enableextensions disabledelayedexpansion

    rem Part that reads from console, not piped input
    < con (
        set "data="
        set /p "data=Type something: "
    )

    echo(
    echo You have typed: [%data%]
    echo(

    rem Part that reads piped input
    find /v "" 

执行时

W:\>type test.cmd | test.cmd
Type something: this is a test

You have typed: [this is a test]

@echo off
    setlocal enableextensions disabledelayedexpansion

    rem Part that reads from console, not piped input
    < con (
        set "data="
        set /p "data=Type something: "
    )

    echo(
    echo You have typed: [%data%]
    echo(

    rem Part that reads piped input
    find /v ""

【讨论】:

我绝对不想从控制台读取 - 我想要管道输入流。 @Marc,我不确定我是否理解问题所在。此代码仅表明在执行另一个代码后检索管道数据没有任何问题。只需确保您的“初始”命令不会通过分配不同的输入源来消耗管道数据。这样,管道数据将可用于读取它的“最终”命令。不是要解决的问题吗?

以上是关于捕获通过管道传输到批处理文件的真正 STDIN的主要内容,如果未能解决你的问题,请参考以下文章

批处理脚本 - 每天将视频传输到下一个文件夹

如何使用 Python 将标准输入/标准输出通过管道传输到 Perl 脚本

在 Windows 批处理文件中将输入管道输入到 Plink 会添加额外的换行符

捕获 find 的输出。 -print0 到 bash 数组中

批处理脚本从用户获取文件列表输入以馈送到 WinSCP

在Windows批处理中运行命令时管道Unity CLI编译日志文件