开发者

Is there any way to supply stdin/out instead of a file to a program in unix?

I have a command line utility from a third party (it's big and written in Java) that I've been using to help me process some data. This utility expects information in a line delimited file and then outputs processed data to STDOUT.

In my testing phases, I was fine with writing some Perl to create a file full of information to be processed and then sending that file to this third party utility, but as I'm nearing putting this code in production, I'd really prefer to just pipe data to this utility directly instead of first writing that data to a file as this would save me the overhead of having to write unneeded information to disk. Is there any way to do this in unix?

Currently I call the utility as follows:

bin/someapp do-action --option1 some_value --input some_file

I'd like to do something like:

bin/someapp do-a开发者_如何学Goction --option1 some_value --input $piped_in_data

Is anything like that possible without my modifying the third party app?


You should be able to use /dev/stdin:

bin/someapp do-action --option1 some_value --input /dev/stdin

(Note that on some systems, /dev/stdin is a symlink; if your Java program doesn't cope with that, you might have to use /dev/fd/0 or something similar instead.)


You can use "process substitution" in bash to achieve something like what you want.

bin/someapp do-action --option1 some_value --input <(generate_input.sh)

should do the trick. The <(list) part is the process substitution.


Another route, if the /dev/stdin technique isn't suitable for some reason, is to use a 'named pipe'.

If you do

% mkfifo /path/to/file

then this will create a filesystem object with that name, which can act as a conduit between two processes. This is just the same as what happens with a normal pipe, except that processes can refer to the pipe as if it were a normal file. For example:

% mkfifo /tmp/my-fifo
% grep alias ~/.bashrc >/tmp/my-fifo &
[1] 70134
% sed 's/alias/wibble/' /tmp/my-fifo
wibble ls='ls -F'
....
[1]  + done       grep alias ~/.bashrc > /tmp/my-fifo
% 

Here, the grep command is writing to the FIFO exactly as if it were a normal file, and it blocks when the named pipe's buffer fills up. The sed process reads from the pipe (as if it were a normal file), emptying the buffer as it does so.


It is not so easy. /dev/stdin, named pipes and <() process substitution are not accessed by a program in the same way a file would be. In particular it is not possible to fseek(), fsetpos() within such a construct, because its length is not known a priori.

Some functions like fopen(), getc(), fread() etc will work though. So for most programs which simply read input line by line or character by character this will do.

If your program seeks within a file (and maybe does other "more advanced" operations) you would need to create a temporary file unfortunately.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜