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.
精彩评论