web-dev-qa-db-fra.com

Comment comprendre le classement de la redirection de sortie?

J'essaie donc d'apprendre comment passer d'une norme à l'autre et d'une erreur à une autre.

Disons que j'ai un dossier avec here.txt seul.

Donc si je le fais

ls here.txt not-here.txt  1>out  2>&1

Puisque here.txt est présent, j'aurai une sortie à diriger vers le fichier out mais puisque not-here.txt n'est pas présent, une erreur sera envoyée via l'erreur standard, que je redirige vers la norme. avec 2>&1.

Cependant, pourquoi ça ne marche pas:

ls here.txt not-here.txt 2>&1 1>out

Cela ne semble fonctionner que si je redirige après l'instruction standard out? Pourquoi?

10
AJJ

L'ordre des redirections est significatif. Par exemple, la commande

ls > dirlist 2>&1

dirige à la fois la sortie standard et l’erreur standard vers le fichier dirlist, tandis que la commande

ls 2>&1 > dirlist

dirige uniquement la sortie standard vers le fichier dirlist, car l'erreur standard a été dupliquée à partir de la sortie standard (toujours en pointant toujours vers une fenêtre de terminal) avant que la sortie standard ne soit redirigée vers dirlist.

Au début, cela peut sembler contre-intuitif, mais après y avoir réfléchi, nous pouvons le comprendre.


Vous trouvez cette explication dans man bash, dans le chapitre sur la redirection,

REDIRECTION

Avant qu'une commande ne soit exécutée, son entrée et sa sortie peuvent être redirigées à l'aide d'une notation spéciale interprétée par le shell. La redirection permet aux descripteurs de fichier de commandes d'être dupliqués, ouverts, fermés, de se référer à différents fichiers et de modifier les fichiers à partir desquels la commande est lue et écrite. La redirection peut également être utilisée pour modifier les descripteurs de fichier dans l'environnement d'exécution du shell actuel. Les opérateurs de redirection suivants peuvent précéder ou apparaître n'importe où dans une commande simple ou peuvent suivre une commande. Les redirections sont traitées dans l'ordre dans lequel elles apparaissent, de gauche à droite.

Chaque redirection pouvant être précédée d'un numéro de descripteur de fichier peut être précédée d'un mot de la forme {varname}. Dans ce cas, pour chaque opérateur de redirection sauf >&- et <&-, le shell allouera un descripteur de fichier supérieur ou égal à 10 et l'affectera à varname. Si >&- ou <&- est précédé de {varname}, la valeur de varname définit le descripteur de fichier à fermer.

Dans les descriptions suivantes, si le numéro de descripteur de fichier est omis et que le premier caractère de l'opérateur de redirection est <, la redirection fait référence à l'entrée standard (descripteur de fichier 0). Si le premier caractère de l'opérateur de redirection est >, la redirection fait référence à la sortie standard (descripteur de fichier 1).

Le mot suivant l'opérateur de redirection dans les descriptions suivantes, sauf indication contraire, est soumis au développement d'accolade, au développement de tilde, au développement de paramètres et de variables, au remplacement de commande, au développement arithmétique, à la suppression de devis, au développement de chemins d'accès et au fractionnement de Word. Si elle s'étend à plus d'un mot, bash rapporte une erreur.

Notez que l'ordre des redirections est significatif. Par exemple, la commande

ls > dirlist 2>&1

dirige à la fois la sortie standard et l’erreur standard vers le fichier dirlist, tandis que la commande

ls 2>&1 > dirlist

dirige uniquement la sortie standard vers le fichier dirlist, car l'erreur standard a été dupliquée à partir de la sortie standard avant que la sortie standard ne soit redirigée vers dirlist.

Edit: Les lignes de commande suivantes pourraient expliquer ce qui se passe

Préparer

sudodus@xenial32:~$ touch qwerty;rm asdf
rm: cannot remove 'asdf': No such file or directory

Exécuter la commande list pour un fichier existant et un fichier non existant

sudodus@xenial32:~$ ls qwerty asdf
ls: cannot access 'asdf': No such file or directory
qwerty

Rediriger la sortie d'erreur avant de rediriger la sortie standard. Seule la sortie standard est redirigée vers le fichier de sortie.

sudodus@xenial32:~$ ls qwerty asdf 2>&1 > output-file ;echo '---';cat output-file 
ls: cannot access 'asdf': No such file or directory
---
qwerty

Rediriger la sortie d'erreur après avoir redirigé la sortie standard. La sortie d'erreur et la sortie standard sont redirigées vers le fichier de sortie.

sudodus@xenial32:~$ ls qwerty asdf > output-file 2>&1 ;echo '---';cat output-file
---
ls: cannot access 'asdf': No such file or directory
qwerty

Le jeton &> peut être utilisé pour rediriger à la fois l'erreur standard et la sortie standard. Il peut être utilisé dans bash, mais peut ne pas être disponible dans d'autres shells.

sudodus@xenial32:~$ ls qwerty asdf &> output-file ;echo '---';cat output-file
---
ls: cannot access 'asdf': No such file or directory
qwerty
sudodus@xenial32:~$ 
5
sudodus
  • 2>x signifie que le nom de fichier x recevra les données écrites dans le descripteur 2 (également appelé stderr, erreur standard)
  • ... mais lorsque x est spécifié comme &1 cela ne signifie pas "toujours suivre 1"; cela signifie "copie les propriétés actuelles de 1 (et laisse-le ainsi)" ".
  • Les redirections sont appliquées dans le même ordre que celui entré sur la ligne de commande, mais avant l'exécution réelle.

C’est la raison pour laquelle 2>&1 1>whatever envoie le signal stderr au terminal.

C'est pourquoi find / -name mylostfile.txt 3>&1 1>&2 2>&3 | grep -v 'Permission denied' échange stderr et stderr, de sorte que vous puissiez filtrer certaines lignes stderr courantes, tout en conservant la totalité de la sortie standard. (Le descripteur 3 ici n'est pas utilisé par les programmes).

3
kubanczyk

Le shell rencontre et définit dans l’ordre où il voit les choses. Dans le premier cas:

ls here.txt not-here.txt  1>out  2>&1

La sortie est redirigée, puis l'erreur type est envoyée au même endroit.

Dans le second cas,

ls here.txt not-here.txt 2>&1 1>out

La sortie standard en sortie est toujours définie sur le terminal. Une erreur standard est donc envoyée au terminal, puis la sortie standard en est modifiée. Le shell a déjà défini l’erreur standard.

2
jpezz