I read a few lines from STDIN. How can I pass the remaining of STDIN to a command that reads from standard input (e.g. md5sum or wc)?
I could do a:
read_a_few_lines_from_diamond_operator();
open (C, "|cmd");
while(<>) { print C }
close C;
cleanup_after_C();
but for efficency reasons I would like not to touch the input, but instead pass the filehandle of STDIN. Sort of like:
seq 10 | (read A; wc)
where read reads as much as it likes before passing the rest on to wc. I cannot use this solution, though, as I need to start the command from inside my perl program and I need to do work after cmd completes.
I read a few lines from the file ‘foo’. How can I pass the remaining to a command that reads from standard input (e.g. md5sum or wc)?
I could do a:
open (F, "<foo");
read_a_few_lines_from_F();
open (C, "|cmd");
while(<F>) { print C }
close C;
cleanup_after_C();
but for efficency reasons I would like not to touch the input, but instead pass the rest of file ‘foo’.
I have a feeling it can to be done using trickery like select, open(FOO,">&STDOUT), exec 6<&0, fork, pipe.
The answer is quite simple: You don’t need to do anything special. Your child will automatically inherit your
STDINwithsystemandexec. Everything you haven’t read from STDIN will be readable by the child.There is a problem, though. Because reading one character at a time would be crazy inefficient, Perl reads from the file a block at a time. That is to say you read more from the file than the “few lines” you got back from Perl. This can clearly be seen using the following command:
Instead of starting at the start of the second line,
catstarts in the middle of the “q”s (at byte 8192)!You’d have to switch from reading lines with
readline(<>) to reading individual bytes withsysreadif you wanted this to work.Focusing on the bigger picture, I think there is a solution:
Or maybe even:
Untested.