Sono nuovo di Linux e sto cercando di capire come funzionano i reindirizzamenti.
Ho testato varie sintassi per reindirizzare stdout
e stderr
allo stesso file, che non producono tutti gli stessi risultati.
Ad esempio, se provo a elencare 2 file che non esistono (file1
e file2
) e 2 che lo fanno (foo
e fz
):
Sintassi n. 1 (senza reindirizzamento):
$ ls file1 foo fz file2
Ecco l'output che ottengo nel terminale:
ls: cannot access file1: No such file or directory
ls: cannot access file2: No such file or directory
foo fz
Sintassi n. 2:
Ora, con reindirizzamento:
$ ls file1 foo fz file2 > redirect 2>&1
Il redirect
contiene lo stesso risultato per la sintassi n. 1:
ls: cannot access file1: No such file or directory
ls: cannot access file2: No such file or directory
foo
fz
Quindi, con entrambe le sintassi precedenti, sembra che la shell stampi stderr
prima, poi stdout
.
Sintassi n. 3:
Ora, se provo con una delle seguenti sintassi:
$ ls file1 foo fz file2 > redirect 2> redirect
o
$ ls file1 foo fz file2 2> redirect > redirect
Quindi il redirect
il file conterrà questo:
foo
fz
nnot access file1: No such file or directory
ls: cannot access file2: No such file or directory
Qui sembra stdout
viene stampato prima di stderr
, ma poi vediamo che l'inizio di stderr
è "ritagliato" dello stesso numero di caratteri di stdout
.
Il stdout
è lungo 6 caratteri (foo fz
, ritorno a capo incluso), quindi i primi 6 caratteri di stderr
(ls: ca
) sono stati sovrascritti da stdout
.
Quindi in realtà sembra stderr
è stato stampato per primo e quel stdout
è stato quindi stampato su stderr
invece di essere aggiunto ad esso.
Tuttavia, per me avrebbe avuto più senso se stderr
era stato completamente cancellato e sostituito con stdout
, piuttosto che solo parzialmente overwitted.
Sintassi #4:
L'unico modo che ho trovato per correggere la sintassi n. 3 è aggiungere l'operatore append a stdout
:
$ ls file1 foo fz file2 >> redirect 2> redirect
o
$ ls file1 foo fz file2 2> redirect >> redirect
Che produce la stessa sintassi n. 2:
ls: cannot access file1: No such file or directory
ls: cannot access file2: No such file or directory
foo
fz
Questo articolo qui spiega che la sintassi n. 3 è sbagliata (presumibilmente, lo è anche la sintassi n. 4). Ma per amor di discussione:perché la sintassi n. 3 è sbagliata? Cosa sta dicendo esattamente (o non dicendo) fare la shell al contrario della sintassi n. 2?
Correlati:qual è la differenza tra $(…) e `…` in Bash?
Inoltre, c'è un motivo per cui l'output mostra sempre stderr
prima di stdout
?
Grazie!
Risposta accettata:
È proprio come eseguire due processi per scrivere sullo stesso file contemporaneamente... pessima idea. Ti ritrovi con due diversi handle di file aperti e i tuoi dati possono essere confusi (come accade nel n. 3 sopra). L'uso della sintassi n. 2 è corretto; ne fa uno gestisce il file e punta sia stderr che stdout nello stesso punto.
Per quanto riguarda lo stderr che viene sempre stampato per primo, non esiste alcuna regola su questo. Sospetto con ls
è perché ls
deve controllare ogni voce nella directory prima che possa effettivamente affermare che un particolare file non esiste. Quindi, anziché eseguire N passaggi sulla tabella delle directory, esegue un unico passaggio, controllando tutti gli argomenti della riga di comando forniti, segnala gli errori e stampa i file trovati. Altri comandi possono stampare su stderr dopo stdout, o anche alternarsi tra loro.