Before the shell executes the
cat command on the command line, it looks for redirections.
There are two redirections:
>file1 This will make the command's standard output go to
<file2 This will make the command's standard input come from
The fact that these redirections are placed in a wonky location on the command line doesn't matter.
$ cat <file2 >file1
is the same as
$ <file2 cat >file1
which is the same as
$ <file2 >file1 cat
Note that the
cat utility in all of these instances is executed without any command line arguments. The redirections are not operands to the
cat command, they are instructions to the shell to set up redirections into and out of the command (connecting its standard input and output to files). The shell sets up the redirections before invoking the command.
The difference between
cat file and
cat <file (or, if you will,
<file cat) is that in the first case, the
cat utility itself is opening the file, which is given as an operand on the command line, for reading, while in the second case, the shell will open the file and connect
cat's input stream to it². In the second case,
cat will notice it wasn't given a file operand and will automatically switch to reading from its standard input. This is a feature of
cat, and of some other utilities, not something that all utilities do.
cat will also read from its standard input if it's given the operand
-. Again, this is special only to
cat and to some other utilities (i.e. nothing that the shell does). To use
cat on a file in the current directory whose name is
-, add a path to the filename, such as
¹ The order of the redirections is still important under some circumstances; With
cat <file2 >file1, for example,
file1 will not be truncated if
file2 is inaccessible (the redirections are parsed from left to right). The relative placement of the word
cat is however still arbitrary and won't influence this.
² See also the question "cat gives different error when opening non-existing file".
The fact that the shell sets up the redirections before even executing the command on the command line is why things like these fail and you end up with an empty output file:
$ sort file >file
Here, the shell will truncate (empty) the file
file before executing
sort file and connecting
sort's standard output to the file. The
sort utility will then open
file and sort its contents (which is nothing). The result (nothing) is passed through the standard output stream to
The remedy in this particular case (for sorting a file "in-place") is
$ sort -o file file
$ sort file >file.sorted && mv file.sorted file
which is more or less what
sort does when using the
-o file to specify the output file name.
Just to back up the statement that the redirections may precede the actual name of the utility on the command line:
A "simple command" is a sequence of optional variable assignments and redirections, in any sequence, optionally followed by words and redirections, terminated by a control operator. [ref: POSIX Shell Command Language 2.9.1 Simple Commands]
And also about the redirection not being part of the operands of the utility:
The optional number, redirection operator, and word shall not appear in the arguments provided to the command to be executed (if any). [ref: POSIX Shell Command Language 2.7 Redirection]