0

I'm new to Unix and trying to understand how pipe works. I thought that I got it so I tried the following example which did not work:

(base) MacBook-Pro:Code usr$ echo "file.txt ~/.Trash" | mv
usage: mv [-f | -i | -n] [-v] source target
       mv [-f | -i | -n] [-v] source ... directory

I was wondering what went wrong.

Thanks, Daniel

daniel
  • 1

1 Answers1

1

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 sources 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 manual 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.

fra-san
  • 10,205
  • 2
  • 22
  • 43