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 stdin
.
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 stdin
.
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.
xargs
(never bothered to Google about it or read the man page), but that makes sense. The only time I've ever used xargs is to open a list of files in vim, a lafind *.rb | xargs vim
. Now I understand what that's doing and why that works whenfind *.rb | vim
doesn't. Thanks! – Nathan Wallace Oct 03 '13 at 20:10