A pipe connects the standard output of the process on its left hand to the standard input o the process on its right hand. echo "file.txt ~/.Trash"
writes file.txt ~/.Trash
on its standard output and the pipe makes that string available to mv
for reading.
Yet, mv
doesn't read from standard input at this point: as the error message you quoted implies, it instead expects to receive at least two command line arguments (one source
and one target
or one or more source
s and one directory
. It complains about seeing none and exits.
(Note that mv
wouldn't read from its standard input even if you invoked it the way it requires, e.g. running echo foo | mv source dest
. It only uses standard input when it needs to interact with the user, for instance when prompting for confirmation).
Indeed not every program reads from standard input. The usage of standard streams on part of programs is explained in their man
ual pages. Those of POSIX utilities have dedicated sections for "STDIN", "STDOUT" and "STDERR", while other versions are less formally organized and may need to be read in full.
No rules dictate how a program should use the standard streams. As stated in the answers to the proposed duplicate target, it mainly relates to the program's semantics. Simplifying more than a bit, programs that deal with streams of data tend to use their standard input/output, while programs that deal with operating system objects (files, directories, processes, users...) tend to only take command line arguments instead.
Finally coming to the specific point your questions seems to raise: only a subset of the *nix utilities that read from standard input use it for reading commands. Only those that are, broadly speaking, interpreters: mainly shells (the standard sh
, bash
, zsh
...) and utilities oriented towards text processing (though not limited to the processing of text; e.g. awk
, grep
, sed
...), but also calculators (bc
) and surely others that refuse to come to my mind right now.
As most of the tools aimed at managing *nix systems, mv
is not designed to parse a string into distinct elements. In the usual division of tasks, that one is the role of the shell, which in turn calls tools as mv
to perform specific actions (based) on arguments whose individual meaning is well defined (and often made clear by the documentation, as in mv [-f | -i | -n] [-v] source target
).
To illustrate this point: while you can not tell mv
what to do via its standard input, and need to type mv foo bar
instead, you can do echo "mv foo bar" | sh
. The sh
interpreter, which reads commands from standard input if it receives no file arguments, takes care of parsing it and invokes mv
with the two arguments foo
and bar
.