Reputation: 15371
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.
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
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
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
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
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