Quelles sont les différences entre &> et 2> & 1

30

Il existe deux formes de redirection de la sortie standard et de l'erreur standard vers la sortie standard . Mais lequel est le meilleur? et pourquoi le &>est considéré comme le parfait?

Je ne trouve pas quelles sont les différences, de sorte que de nombreux didacticiels et même un manuel bash &>sont meilleurs!

Alors, pourquoi dois-je utiliser &>et non2>&1

Utilisant principalement la bashcoquille


EDIT: Merci pour les commentateurs

Uniquement> & fonctionne en csh ou tcsh

Dans ksh, seulement 2> & 1 fonctionne.

utilisation du tiret> fichier 2> & 1 redirection uniquement

Ensuite, lequel utiliser pour garantir que mon script est compatible avec d'autres systèmes quels que soient les shells utilisés!

Maythux
la source
le meilleur est ce qui fait ce que vous devez faire. ceux-ci font des choses très différentes. quel shell utilisez-vous?
Skaperen
@Skaperen using bash
Maythux
1
que voulez- vous accomplir?
Skaperen
Je veux juste savoir quelles sont les différences, ce que je veux c'est ne pas les deux mais j'ai juste besoin de savoir si c'est une différence pour qu'une fois soit préférée aux autres
Maythux
2
&> somewhereest juste un raccourci bash pour > somewhere 2>&1: selon les termes du manuel bash, ils sont "symantiquement équivalents"
steeldriver

Réponses:

23

La page de manuel de Bash mentionne qu'il existe deux façons de rediriger stderr et stdout : &> file et >& file. Maintenant, notez qu'il indique à la fois stderr et stdout.

Dans ce cas, >file 2>&1nous faisons la redirection de stdout (1) vers le fichier, mais nous demandons également à stderr (2) d'être redirigé au même endroit que stdout! Le but peut donc être le même, mais l'idée légèrement différente. En d'autres termes "John, va à l'école; Suzzie va où John va".

Et la préférence? &>est une bashchose. Donc, si vous portez un script, cela ne le fera pas. Mais si vous êtes certain à 100% que votre script ne fonctionnera que sur le système avec bash - alors il n'y a pas de préférence

Voici un exemple avec dash, le Debian Amquist Shell qui est la valeur par défaut d'Ubuntu.

$ grep "YOLO" * &> /dev/null
$ grep: Desktop: Is a directory
grep: Documents: Is a directory
grep: Downloads: Is a directory
grep: Music: Is a directory
grep: Pictures: Is a directory
grep: Public: Is a directory
grep: Templates: Is a directory
grep: Videos: Is a directory
grep: YOLO: Is a directory
grep: bin: Is a directory

Comme vous pouvez le voir, stderr n'est pas redirigé

Pour répondre à vos modifications dans la question, vous pouvez utiliser l'instruction if pour vérifier la variable $ SHELL et modifier les redirections en conséquence

Mais pour la plupart des cas, cela > file 2>&1devrait fonctionner


En termes plus techniques, le formulaire [integer]>&words'appelle Duplicating Output File Descriptor et est une fonctionnalité spécifiée par la norme POSIX Shell Command Language, qui est prise en charge par la plupart des shells conformes à POSIX et de type Brourne.

Voir aussi Que signifie & signifie exactement dans la redirection de sortie?

Sergiy Kolodyazhnyy
la source
Que se passe-t-il alors lors de l'utilisation sur d'autres coques?
Maythux
zsh prend en charge &>.... @Maythux Dans les shells qui ne prennent pas en charge &>par exemple, dashvous devez utiliser la >file 2>&1redirection triviale ..
heemayl
Alors lequel utiliser si je veux être sûr que mon script sera compatible avec différents shells
Maythux
3
@Maythux Use >file 2>&1. Ce travail sur tous les obus
Sergiy Kolodyazhnyy
1
Les shells @ TSJNachos117 définis /etc/passwdpour chaque utilisateur sont des shells interactifs. dash Sauf indication contraire, les scripts système sont généralement destinés à. Quant à ce qui est par défaut, il est déterminé par ce qui est lié à /bin/shDans le cas d'Ubuntu, c'est dash. Dans RHEL c'est le cas bash, dans FreeBSD c'est la tcsh source et une autre source
Sergiy Kolodyazhnyy
7

Je recommanderais généralement de suivre la façon de faire de Bourne-again SHell , car bash est sans doute le shell Unix le plus populaire. Bash utilise généralement soit &>ou 2>&1. À mon humble avis, ni l'un ni l'autre n'est "parfait", donc je recommande d'oublier ce non-sens. De manière réaliste, celui que vous devez utiliser dépend de ce que vous essayez de faire.

2>&1fusionne stderr avec stdout, ce qui peut être utile si, par exemple, vous souhaitez diriger le texte stderr. Ainsi, par exemple, si vous voulez voir si un programme imprime un certain message stderr, mais ne voulez pas que votre écran soit rempli (probablement) de déchets sans importance, vous pouvez faire quelque chose comme program 2>&1 | grep crashed, qui recherchera la stdout et la stderr d'un programme appelé "programme" pour le mot "planté".

D'un autre côté, si vous ne voulez pas qu'un programme imprime quoi que ce soit, vous pouvez simplement exécuter program &> /dev/null, qui redirigera stderr et stdout vers / dev / null, un fichier spécial qui fait magiquement disparaître les choses. Ou, si vous souhaitez enregistrer la sortie d'un programme (peut-être pour signaler un bogue ou quelque chose), vous pouvez rediriger stderr et stdout vers un fichier: program &> log.txtredirigera toutes les données vers un fichier appelé "log.txt". Si vous le souhaitez, vous pouvez rediriger stdout et stderr via program 2> log.txt > log.txtou program 2>&1 | cat > log.txt, les deux ayant le même effet que l'utilisation &>. Si vous faites quelque chose comme ça program 2>&1 > file, seul stdout sera redirigé, mais stderr peut toujours être redirigé vers un autre programme, tel que cat, qui pourrait être redirigé comme indiqué ci-dessus. Cependant, en tapant&>est plus facile que n'importe lequel des exemples ci-dessus, car cela implique de taper moins de caractères (et c'est un peu plus facile à lire pour les êtres humains). Notez que cela program 2> log.txt > log.txtpourrait être plus susceptible de fonctionner sur des shells non bash.

PS: si vous craignez que les gens utilisent d'autres shells, il y a quelque chose que vous pouvez ajouter pour être la première ligne de votre script appelée "nombre magique", ou "shebang". C'est essentiellement un moyen de s'assurer que les autres ordinateurs (en particulier ceux qui exécutent des systèmes d'exploitation de type Unix) savent quel programme utiliser pour exécuter un script. Différents scripts utilisent différents shebangs. Un shebang pour un script bash ressemble à ceci:

#!/bin/bash

Si vous utilisez ce qui précède comme première ligne d'un script donné, bash sera généralement utilisé pour exécuter ledit script. Cela rendra beaucoup plus difficile pour quelqu'un d'exécuter accidentellement le script avec le mauvais shell.

PS: Je ne vais pas mentir: jusqu'à présent, je ne savais pas qu'on pouvait utiliser >&, mais, en ce qui concerne bash, il semble faire de même &>. Vous apprenez quelque chose de nouveau tous les jours.

TSJNachos117
la source
Bien que je sois d'accord avec vous sur l'utilisation de la #!ligne pour demander explicitement bash, elle n'est pas toujours disponible sur d'autres systèmes. Très souvent, les développeurs / administrateurs système doivent écrire des scripts portables pour les systèmes sur lesquels il se bashpeut qu'ils ne soient pas disponibles et que l'installation ne soit pas sous leur contrôle bash. Le >file 2>&1est tout simplement très portable.
Sergiy Kolodyazhnyy
Vous avez fait une erreur d'annulation ci-dessus, qui ne produit pas le résultat que vous réclamez ou souhaitez. Rediriger stderr vers stdout, puis rediriger stdout laisse stderr sur la stdout d'origine.
ubfan1
Serg: Je ne voulais pas impliquer que bash était universel. Cependant, je pense que plus de gens l'utilisent que disent (t) csh. Si vous ne savez pas ce que quelqu'un d'autre utilise et que vous devez deviner à l'aveugle, bash est probablement votre meilleur pari. De plus, je ne connais généralement pas la portabilité, car j'utilise uniquement bash. Le fait qu'il >file 2>&1soit plus portable est bon à savoir. Je ferai une modification pour refléter cela.
TSJNachos117
Ubfan1, merci pour l'info. Je n'aurais jamais deviné depuis un million d'années que bash ne redirigerait pas stderr vers un fichier dans ce cas. Je viens de modifier ma réponse pour empêcher les autres de faire la même erreur.
TSJNachos117
4

Depuis le manuel de référence de Bash -> 3.6.4 Redirection de la sortie standard et de l'erreur standard :

Cette construction permet de rediriger à la fois la sortie standard (descripteur de fichier 1) et la sortie d'erreur standard (descripteur de fichier 2) vers le fichier dont le nom est l'expansion du mot.

Il existe deux formats pour rediriger la sortie standard et l'erreur standard:

&>word

et

>&word

Des deux formes, la première est préférée. C'est sémantiquement équivalent à

>word 2>&1

Lorsque vous utilisez le deuxième formulaire, le mot peut ne pas se développer en un nombre ou «-». Si c'est le cas, d'autres opérateurs de redirection s'appliquent (voir Duplication des descripteurs de fichiers ci-dessous) pour des raisons de compatibilité.

Aussi bon de se référer au wiki de Greg sur Input And Output -> 4.2. Manipulation du descripteur de fichier :

Pour plus de commodité, Bash met également à votre disposition une autre forme de redirection. L'opérateur de redirection &> n'est en fait qu'une version plus courte de ce que nous avons fait ici [ 2>&1]; rediriger stdout et stderr vers un fichier.

fedorqui
la source
4

Alors pourquoi utiliser &> et non 2> & 1

2>&1 est un shell Bourne / POSIX standard.

&>est une extension bash et non de jure standard.

Si vous écrivez des scripts à l'aide d'extensions bash, vous rencontrerez tôt ou tard des échecs effrayants avec des messages d'erreur de syntaxe cryptique car ils sont exécutés dans un shell standard.

Stephen M. Webb
la source