Thomas W
Thomas W

Reputation: 15371

passing on piped data in batch file

The situation

I'm sitting at the receiving end of program A (redmon, a port monitor). I need to write a batch script that program A can call to pipe a large amount of data (PostScript) into.

Whenevern program A calls my batch script, I need to pass that data on to program B (Ghostscript) and eventually have program C (called dosomething here) do something with the output of program B.

How it would work with Bash (Unix shell)

In a bash script, I'd write a script (let's call it myscript.sh) like:

#!/bin/bash
cat - | gs -sDEVICE=pdfwrite -o test.pdf -f -
dosomething test.pdf

This would work work perfectly when one pipes some data into it:

cat testdata.ps | myscript.sh

Will it work on with a Windows Batch file?

As this is for Windows, I need something that can be called like

type testdata.ps | myscript.bat

because, effectively, this is how program A would call myscript.bat. So I tried translating the bash approach 1:1 to a batch file:

@echo off
type con | "%PROGRAMFILES%\gs\gs9.16\bin\gswin32c" -o test.pdf -f -
dosomething test.pdf

The problem is, type con doesn't seem to recognize when there's nothing left to process and the batch script therefore hangs. So, what can I do?

I tried if it might work in reverse, like

"%PROGRAMFILES%\gs\gs9.16\bin\gswin32c" -o test.pdf -f - < CON

but no luck either. An attempt at copying CON to a file failed as well

copy con test.ps

How would one go about this? It all boils down to capturing the entire piped content and recognizing when program A is closing the pipe.

Upvotes: 1

Views: 6279

Answers (3)

Harry Johnston
Harry Johnston

Reputation: 36328

You're trying too hard; Windows will do what you want by default, so you just need to say

@echo off
"%PROGRAMFILES%\gs\gs9.16\bin\gswin32c" -o test.pdf -f -
dosomething test.pdf

The reason type con or < CON don't work is that CON is the local console device and is not affected by redirection.

(Incidentally, I think this is also true in Linux; using cat - | myprog is harmless but redundant.)

Upvotes: 3

aschipfl
aschipfl

Reputation: 34919

To tell con to stop you need to pass over an end-of-file character (code 26 or 0x1A), which can be achieved by pressing <Ctrl+Z> in command prompt.

So copy con test.ps will work when you terminate your input that way. (You still have to press <enter> finally; everything after the end-of-file will be discarded.)

The end-of-file code is displayed as ^Z in command prompt.

Upvotes: 1

rojo
rojo

Reputation: 24476

In batch scripting, if you want to capture input from a pipe, use set /P. Here's an example:

@echo off
setlocal

set /p "piped="

echo piped: %piped%

Example session:

command: echo Hello world! | batfile.bat
output: piped: Hello world!


For extra credit, you can code your script so that it'll accept input either via argument or pipe.

@echo off
setlocal

if "%~1"=="" (
    set /p "input="
) else set "input=%*"

echo input: %input%

In that example, if there is no Argument 1, then capture from stdin. Otherwise, set input=all arguments.

command: echo Hello world! | batfile.bat
output: input: Hello world!

command: batfile.bat Hello World!
output: input: Hello world!

command: >textfile.txt echo Hello world!
command 2: batfile.bat < textfile.txt
output: input: Hello world!


Be advised that set /P "var=Question?" stops capturing as soon as it receives a new line. So it's not well-suited for binary streams I don't think. You will probably have to save the PostScript stream to a .ps file, then gswin32c -o test.pdf temp.ps or similar.

I'm not really clear on what you mean by being at the receiving end of Program A. Do you have control over Program A's command line? If so, why not Program A | gswin32c -o test.pdf -?

Upvotes: 3

Related Questions