Whether a program takes its input from
stdin or as command line arguments is up to the designer. Both approaches have their merits. For programs that operate strictly on files, however, it's usually more convenient to pass the filenames as command line arguments rather than through
The most obvious reason is that the common case, that of just running a program on a file, is easier to type:
readlink file instead of
echo file | readlink.
A subtler issue is correctness. The problem is that when filenames are passed through
stdin, the program needs to be able to distinguish one filename from another. Often, this is done by assuming the filenames are separated by whitespace or newlines, but this is incorrect since filenames can include whitespace. A better way is to separate the filenames with null bytes, but it can be inconvenient to generate a list of files separated by nulls.
Passing filenames on the command line avoids this problem because the shell handles all the parsing and quoting for the program. You can type
touch $'foo\nbar' and
touch correctly sees this as one filename containing a newline, without having to handle any special parsing or quoting itself.
All that being said, if you'd like to pass files through
stdin for a particular program, you can. This is what
xargs is for.
xargs lets you take a program that only accepts arguments on the command line, and instead make it take its arguments through
In other words, it lets you do this:
which my_script | xargs readlink.
If you wanted to always make
readlink work this way, you could make an alias:
alias readlink="xargs readlink". That would allow you to type
which my_script | readlink, as you originally wanted.