Order of redirections

I find it easier to think of using assignments.

  • > is like =
  • & is like $

You start out with

1 = /dev/tty
2 = /dev/tty

then your first example, 1> file.txt 2>&1, does

1 = file.txt
2 = $1           # and currently $1 = file.txt

leaving you with

1 = file.txt
2 = file.txt

If you did it the other way, again you start with

1 = /dev/tty
2 = /dev/tty

then 2>&1 > file.txt does

2 = $1           # and currently $1 = /dev/tty
1 = file.txt

so the end result is

1 = file.txt
2 = /dev/tty

and you've only redirected stdout, not stderr.

The order of redirection is important, and they should be read left to right.

For example: command 2>&1 >somefile means:

  1. Redirect the descriptor named 2 (bound to stderr) to the current destination of 1 (stdout) which at this point, reading left-ot-right is the terminal.
  2. Then change 1 (stdout) to go to somefile, which is a a file in disk

So in this case, stderr goes to the terminal, and stdout goes to a file, which isn't what you probably want.

On the other hand, command >somefile 2>&1 means:

  1. Redirect stdout to somefile
  2. Then redirect stderr to the same destination as stdout (somefile).

In this last case both stderr and stdout go to somefile, which is probably what you want.

cat file1 file2 1> file.txt 2>&1

>& Actually means duplicate, it uses the dup system call to to map a new file descriptor onto an already opened file.

So, you (bash actually) must first open the new stdout before, saying " and redirect stderr to whatever stdout is currently set."