grep
and sed
ignore stdin if you provide a filename parameter:
$ echo foo > test.txt
$ echo foobar | grep f test.txt
foo
$ echo foobar | sed -e 's/foo/bar/' test.txt
bar
Is this established best practice? If so, why?
grep
and sed
ignore stdin if you provide a filename parameter:
$ echo foo > test.txt
$ echo foobar | grep f test.txt
foo
$ echo foobar | sed -e 's/foo/bar/' test.txt
bar
Is this established best practice? If so, why?
The Answer I found is that's how it is designed. If you want to read from both stdin and file use echo foobar | grep f - test.txt
. from man grep
grep searches the named input FILEs (or standard input if no files are
named, or if a single hyphen-minus (-) is given as file name) for lines
containing a match to the given PATTERN. By default, grep prints the
matching lines.
A program knows whether files are specified on its command line. It cannot know whether there is any input available on stdin (other than by trying to read it), and if there is input, there is no way for the program to know whether that input was intended for it. So the only sensible option is to have a clear rule, based on how the program was invoked (command line arguments, environment variables, configuration files, …), to decide whether it will read from stdin or not.
For example, typical text utilities (cat
, sort
, grep
, awk
, perl -p
, …) read from stdin if no file is provided, and read from the specified file(s) if there are any. Interpreters obey a similar convention, for example sh
with no arguments reads commands from standard input while sh script_file_name
reads commands from the specified file (and leaves stdin to be read by the script if it wants). There is also a common convention that if -
appears in a position where the name of an input file is expected, the program will read from stdin.
Consider a shell snippet like
somecommand | while read line; do
process "$line"
done
You need to know whether process
reads from stdin or not. There's no such thing as “testing whether stdin is provided”: it's there, but the user who invokes the program knows whether he wants stdin to be read or not.
foo filename -
for both filename and stdin(the-
), only read from stdin if you are told to OR no filename is provided. – cjh Dec 30 '12 at 01:31