shell standard streams redirection order
The order matters as the outcome is different. Take your first example:
ls -al /doesNotExists 2>&1 1>/dev/null
This directs only standard output to nul, because the standard error was duplicated to standard output before standard output was redirected to dirlist.
ls -al /doesNotExists 1>/dev/null 2>&1
This directs both standard output and standard error to nul.
Bash Reference Manual: Redirections
Note that the order of redirections is significant. For example, the
command
ls > dirlist 2>&1
directs both standard output (file descriptor 1) and standard error
(file descriptor 2) to the file dirlist, while the command
ls 2>&1 > dirlist
directs only the standard output to file dirlist, because the standard
error was made a copy of the standard output before the standard
output was redirected to dirlist.
Source Bash Reference Manual: Redirections
Tutorial
There is a nice illustrated tutorial at Illustrated Redirection Tutorial which makes this easier to understand:
Order Of Redirection, i.e., "> file 2>&1" vs. "2>&1 >file"
While it doesn't matter where the redirections appears on the command
line, their order does matter. They are setup from left to right.
2>&1 >file
A common error, is to do command 2>&1 > file to redirect both stderr
and stdout to file. Let's see what's going on. First we type the
command in our typical terminal, the descriptors look like this:
--- +-----------------------+
standard input ( 0 ) ---->| /dev/pts/5 |
--- +-----------------------+
--- +-----------------------+
standard output ( 1 ) ---->| /dev/pts/5 |
--- +-----------------------+
--- +-----------------------+
standard error ( 2 ) ---->| /dev/pts/5 |
--- +-----------------------+
Then our shell, Bash sees 2>&1 so it duplicates 1, and the file
descriptor look like this:
--- +-----------------------+
standard input ( 0 ) ---->| /dev/pts/5 |
--- +-----------------------+
--- +-----------------------+
standard output ( 1 ) ---->| /dev/pts/5 |
--- +-----------------------+
--- +-----------------------+
standard error ( 2 ) ---->| /dev/pts/5 |
--- +-----------------------+
That's right, nothing has changed, 2 was already pointing to the same
place as 1. Now Bash sees > file and thus changes stdout:
--- +-----------------------+
standard input ( 0 ) ---->| /dev/pts/5 |
--- +-----------------------+
--- +-----------------------+
standard output ( 1 ) ---->| file |
--- +-----------------------+
--- +-----------------------+
standard error ( 2 ) ---->| /dev/pts/5 |
--- +-----------------------+
And that's not what we want.
>file 2>&1
Now let's look at the correct command >file 2>&1. We start as in the
previous example, and Bash sees > file:
--- +-----------------------+
standard input ( 0 ) ---->| /dev/pts/5 |
--- +-----------------------+
--- +-----------------------+
standard output ( 1 ) ---->| file |
--- +-----------------------+
--- +-----------------------+
standard error ( 2 ) ---->| /dev/pts/5 |
--- +-----------------------+
Then it sees our duplication 2>&1:
--- +-----------------------+
standard input ( 0 ) ---->| /dev/pts/5 |
--- +-----------------------+
--- +-----------------------+
standard output ( 1 ) ---->| file |
--- +-----------------------+
--- +-----------------------+
standard error ( 2 ) ---->| file |
--- +-----------------------+
And voila, both 1 and 2 are redirected to file.
n>&m
as, redirect streamn
to wherem
is currently directed to. Not redirect streamn
to streamm
.