La duplicazione è davvero la parte importante qui.
Vediamo dove andranno i descrittori di file prima del reindirizzamento. Questo è normalmente il terminale corrente, ad es .:
STDOUT ---> /dev/pts/1
STDERR ---> /dev/pts/1
Ora, se chiamiamo ls -l
senza reindirizzamento, i messaggi di output e di errore vanno al mio terminale sotto /dev/pts/1
.
Se prima reindirizziamo STDOUT
a un file ( ls -l > dirlist
), è simile al seguente:
STDOUT ---> /home/bon/dirlist
STDERR ---> /dev/pts/1
Quando reindirizziamo quindiSTDERR
a un duplicato del STDOUT
descrittore di file ( ls -l > dirlist 2>&1
), si STDERR
passa a un duplicato di /home/bon/dirlist
:
STDOUT ---> /home/bon/dirlist
STDERR ---> /home/bon/dirlist
Se per prima cosa reindirizzassimo STDERR
a un duplicato del STDOUT
descrittore di file ( ls -l 2>&1
):
STDOUT ---> /dev/pts/1
STDERR ---> /dev/pts/1
e quindi STDOUT
su un file ( ls -l 2>&1 > dirlist
), otterremmo questo:
STDOUT ---> /home/bon/dirlist
STDERR ---> /dev/pts/1
Qui, STDERR
sta ancora andando al terminal.
Vedi, l'ordine nella pagina man è corretto.
Test del reindirizzamento
Ora puoi provarlo tu stesso. Usando ls -l /proc/$$/fd/
, vedi dove STDOUT
(con fd 1) e STDERR
(con fd 2), stanno andando per il processo corrente:
$ 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
Creiamo un piccolo script shell che mostra dove sono puntati i descrittori dei tuoi file. In questo modo, otteniamo sempre lo stato durante la chiamata ls
, incluso qualsiasi reindirizzamento dalla shell chiamante.
$ cat > lookfd.sh
#!/bin/sh
ls -l /proc/$$/fd/
^D
$ chmod +x lookfd.sh
(Con CtrlD, si invia un end-of-file e quindi si interrompe la cat
lettura del comando STDIN
.)
Ora chiama questo script con varie combinazioni di reindirizzamento:
$ ./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
Puoi vedere che i descrittori di file 1 (per STDOUT
) e 2 (per STDERR
) variano. Per divertimento, puoi anche reindirizzare STDIN
e vedere il risultato:
$ ./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
(Domanda lasciata al lettore: dove punta il descrittore di file 255? ;-))