Marc
Marc

Reputation: 14313

Capturing true STDIN piped to a batch file

I want to access STDIN from inside a batch file after some other commands. I know that the first command in a .BAT file receives STDIN but I want to first run some other commands and then capture STDIN. I also want this to work with streamed STDIN i.e. it is not acceptable to capture STDIN to a file at the start with (see workaround below).

Now, I understand that CON is the "file" representing STDIN and that TYPE CON would output (echo) STDIN. This does not seem to work at all inside a batch file. Indeed, it appears not to represent STDIN but user/host input by keyboard.

test.bat

TYPE CON > output.txt

Test run:

C:>TYPE myfile.txt | test.bat

Expected result: myfile.txt is copied into output.txt.

Actual result: The batch waits for user input (ignores what is piped to it) and writes user input typed on the keyboard to output.txt.

Workaround

As a workaround: the following test.bat works but does not support streamed input (e.g. from a tail command):

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

UPDATE: Back Story: I have a neat CMD which uses powershell to download (via HTTP) an arbitrary .ps1 script (like a package manager would) and execute it on the fly. If I call REMEXEC.bat mymodule foo bar it loads and executes mymodule.ps1 with the parameters foo and bar.

This works wonderfully for every scenario except piped, streamed input. Using the findstr "^" works for piped input but not for an open stream. Using say AWK /.*/ as the first line of my BAT gets me that streamed input but just pushes the problem down the road.

Ultimately I want a something.bat which looks like this (pseudocode):

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

The catch 22 is that downloadPSModule happens BEFORE executePSModule and thus has no access to STDIN (a privelege reserved for the first line of a BAT).

Upvotes: 5

Views: 4292

Answers (1)

MC ND
MC ND

Reputation: 70941

If you need to retrieve input from console or isolate reading from the stdin stream to not consume piped data, I would try directly reading from console with something like

@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 "" 

When executed

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 ""

Upvotes: 1

Related Questions