Ordre des redirections

29

Je ne comprends pas très bien comment l'ordinateur lit cette commande.

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

Si je comprends bien, 2>&1redirigez simplement l'erreur standard vers la sortie standard.

Par cette logique, la commande se lit comme suit:

  1. concaténer des fichiers file1et file2.

  2. envoyer stdoutde cette opération à file.txt.

  3. envoyer stderrà stdout.

  4. fin?

Je ne sais pas ce que fait l'ordinateur. Par ma logique, la commande devrait être

cat file1 file2 2>&1 > file.txt

mais ce n'est pas correct.

iDontKnowBetter
la source

Réponses:

46

Je trouve plus facile de penser à utiliser des affectations.

  • > est comme =
  • & est comme $

Vous commencez avec

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

alors votre premier exemple, 1> file.txt 2>&1, ne

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

te laissant avec

1 = file.txt
2 = file.txt

Si vous l'avez fait dans l'autre sens, vous recommencez avec

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

puis 2>&1 > file.txtfait

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

donc le résultat final est

1 = file.txt
2 = /dev/tty

et vous avez seulement redirigé stdout, non stderr.

Mikel
la source
j'ai en quelque sorte l'analogie, mais c'est déroutant - qu'est-ce que cela signifie $?
Eliran Malka
Dans une affectation comme var=$othervar, $introduit le nom de la variable sur le côté droit. Dans une redirection comme 2>&1, &introduit le numéro de descripteur de fichier sur le côté droit. Je dis que vous pouvez y penser comme "le fichier 2 est égal au fichier 1". (Mais il existe deux types d'égaux: <signifie "pour lire" et >signifie "pour écrire".)
Mikel
12

L'ordre de redirection est important et doit être lu de gauche à droite .

Par exemple: command 2>&1 >somefilesignifie:

  1. Rediriger stderr(à savoir 2) vers la destination actuelle de stdout(à ce stade, le terminal).
  2. Puis changez stdoutpour aller à somefile.

Donc, dans ce cas, stderrva au terminal et stdoutva dans un fichier, ce qui n'est pas ce que vous voulez probablement.

D'autre part, command >somefile 2>&1signifie:

  1. Rediriger stdoutverssomefile
  2. Redirigez ensuite vers stderrla même destination que stdout( somefile).

Dans ce dernier cas stderr, stdoutallez à la fois somefile, ce qui est probablement ce que vous voulez.

Amelio Vazquez-Reina
la source
4
cat file1 file2 1> file.txt 2>&1

>& Signifie en fait un doublon, il utilise l'appel système dup pour mapper un nouveau descripteur de fichier sur un fichier déjà ouvert.

Donc, vous (bash en fait) devez d'abord ouvrir la nouvelle stdout avant, en disant "et rediriger stderr vers la stdout actuellement définie".

X Tian
la source
C'est génial! je me posais des questions à ce sujet &. pourriez-vous joindre quelques références à cette syntaxe, ou - mieux encore - de bonnes ressources sur le système de dup susmentionné?
Eliran Malka
1
'man dup' documente l'appel système.
X Tian
est logique :) merci
Eliran Malka