La duplicación es realmente la parte importante aquí.
Veamos a dónde van los descriptores de archivos antes de la redirección. Este es normalmente el terminal actual, por ejemplo:
STDOUT ---> /dev/pts/1
STDERR ---> /dev/pts/1
Ahora, si llamamos ls -lsin redireccionamiento, los mensajes de salida y error van a mi terminal debajo /dev/pts/1.
Si primero redirigimos STDOUTa un archivo ( ls -l > dirlist), se ve así:
STDOUT ---> /home/bon/dirlist
STDERR ---> /dev/pts/1
Cuando luego redirigimos STDERRa un duplicado del STDOUTdescriptor de archivo ( ls -l > dirlist 2>&1), STDERRva a un duplicado de /home/bon/dirlist:
STDOUT ---> /home/bon/dirlist
STDERR ---> /home/bon/dirlist
Si primero redirigiéramos STDERRa un duplicado del STDOUTdescriptor de archivo ( ls -l 2>&1):
STDOUT ---> /dev/pts/1
STDERR ---> /dev/pts/1
y luego STDOUT a un archivo ( ls -l 2>&1 > dirlist), obtendríamos esto:
STDOUT ---> /home/bon/dirlist
STDERR ---> /dev/pts/1
Aquí, STDERRtodavía va a la terminal.
Verá, el orden en la página del manual es correcto.
Prueba de redireccionamiento
Ahora, puedes probar eso tú mismo. Usando ls -l /proc/$$/fd/, verá dónde STDOUT(con fd 1) y STDERR(con fd 2) van para el proceso actual:
$ ls -l /proc/$$/fd/
total 0
lrwx------ 1 bon bon 64 Jul 24 18:19 0 -> /dev/pts/1
lrwx------ 1 bon bon 64 Jul 24 18:19 1 -> /dev/pts/1
lrwx------ 1 bon bon 64 Jul 24 07:41 2 -> /dev/pts/1
lrwx------ 1 bon bon 64 Jul 24 18:19 255 -> /dev/pts/1
Creemos un pequeño script de shell que muestre dónde apuntan los descriptores de sus archivos. De esta forma, siempre obtenemos el estado al llamar ls, incluida cualquier redirección desde el shell de llamada.
$ cat > lookfd.sh
#!/bin/sh
ls -l /proc/$$/fd/
^D
$ chmod +x lookfd.sh
(Con CtrlD, envía un fin de archivo y así detiene la catlectura del comando STDIN).
Ahora, llame a este script con diferentes combinaciones de redireccionamiento:
$ ./lookfd.sh
total 0
lrwx------ 1 bon bon 64 Jul 24 19:08 0 -> /dev/pts/1
lrwx------ 1 bon bon 64 Jul 24 19:08 1 -> /dev/pts/1
lrwx------ 1 bon bon 64 Jul 24 19:08 2 -> /dev/pts/1
lr-x------ 1 bon bon 64 Jul 24 19:08 255 -> /home/bon/lookfd.sh
$ ./lookfd.sh > foo.out
$ cat foo.out
total 0
lrwx------ 1 bon bon 64 Jul 24 19:10 0 -> /dev/pts/1
l-wx------ 1 bon bon 64 Jul 24 19:10 1 -> /home/bon/foo.out
lrwx------ 1 bon bon 64 Jul 24 19:10 2 -> /dev/pts/1
lr-x------ 1 bon bon 64 Jul 24 19:10 255 -> /home/bon/lookfd.sh
$ ./lookfd.sh 2>&1 > foo.out
$ cat foo.out
total 0
lrwx------ 1 bon bon 64 Jul 24 19:10 0 -> /dev/pts/1
l-wx------ 1 bon bon 64 Jul 24 19:10 1 -> /home/bon/foo.out
lrwx------ 1 bon bon 64 Jul 24 19:10 2 -> /dev/pts/1
lr-x------ 1 bon bon 64 Jul 24 19:10 255 -> /home/bon/lookfd.sh
$ ./lookfd.sh > foo.out 2>&1
$ cat foo.out
total 0
lrwx------ 1 bon bon 64 Jul 24 19:11 0 -> /dev/pts/1
l-wx------ 1 bon bon 64 Jul 24 19:11 1 -> /home/bon/foo.out
l-wx------ 1 bon bon 64 Jul 24 19:11 2 -> /home/bon/foo.out
lr-x------ 1 bon bon 64 Jul 24 19:11 255 -> /home/bon/lookfd.sh
Puede ver que los descriptores de archivo 1 (para STDOUT) y 2 (para STDERR) varían. Por diversión, también puede redirigir STDINy ver el resultado:
$ ./lookfd.sh < /dev/zero
total 0
lr-x------ 1 bon bon 64 Jul 24 19:18 0 -> /dev/zero
lrwx------ 1 bon bon 64 Jul 24 19:18 1 -> /dev/pts/1
lrwx------ 1 bon bon 64 Jul 24 19:18 2 -> /dev/pts/1
lr-x------ 1 bon bon 64 Jul 24 19:18 255 -> /home/bon/lookfd.sh
(Pregunta dejada al lector: ¿Dónde apunta el descriptor de archivo 255? ;-))