¿Cuáles son las diferencias entre &> y 2> & 1

30

Hay dos formas de redireccionar la salida estándar y el error estándar en la salida estándar . ¿Pero cual es mejor? y por qué &>se considera el perfecto?

No puedo encontrar cuáles son las diferencias, por lo que muchos tutoriales e incluso bash manual indican que &>es mejor.

Entonces, ¿por qué debo usar &>y no2>&1

Principalmente usando bashshell


EDITAR: gracias por los comentaristas

Solo> y funciona en csh o tcsh

En ksh solo funcionan 2> & 1.

dash use> file 2> & 1 solo redirección

¡Entonces cuál usar para asegurar que mi script sea compatible con otros sistemas, sean cuales sean los shells usados!

Maythux
fuente
lo mejor es lo que hace lo que necesita hacer. estos hacen cosas muy diferentes. ¿Qué caparazón estás usando?
Skaperen
@Skaperen usando bash
Maythux
1
¿qué es lo que quiere lograr?
Skaperen
Sólo quiero saber cuál es la diferencia, lo que quiero es no haga tanto pero yo sólo necesita saber si el es una diferencia por lo que una vez que se preffred sobre otra
Maythux
2
&> somewherees solo una abreviatura de bash para > somewhere 2>&1: en las palabras del manual de bash, son "equivalentes sintácticamente"
steeldriver

Respuestas:

23

La página de manual de Bash menciona que hay dos formas de redirigir stderr y stdout : &> file y >& file. Ahora, observe que dice tanto stderr como stdout.

En este caso >file 2>&1, estamos redirigiendo stdout (1) al archivo, ¡pero también le estamos diciendo a stderr (2) que se redirija al mismo lugar que stdout! Entonces, el propósito puede ser el mismo, pero la idea es ligeramente diferente. En otras palabras "John, ve a la escuela; Suzzie ve a donde va John".

¿Qué pasa con la preferencia? &>es una bashcosa Entonces, si está portando un script, eso no lo hará. Pero si está 100% seguro de que su script solo funcionará en el sistema con bash, entonces no hay preferencia

Aquí hay un ejemplo con dashDebian Amquist Shell, que es el predeterminado de 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

Como puede ver, stderr no se redirige

Para abordar sus ediciones en la pregunta, puede usar la instrucción if para verificar la variable $ SHELL y cambiar las redirecciones en consecuencia

Pero para la mayoría de los casos > file 2>&1debería funcionar


En términos más técnicos, el formulario [integer]>&wordse denomina Descriptor de archivos de salida duplicados y es una característica especificada por el estándar POSIX Shell Command Language, que es compatible con la mayoría de los shells compatibles con POSIX y similares a Brourne.

Consulte también ¿Qué significa y significa exactamente en la redirección de salida?

Sergiy Kolodyazhnyy
fuente
Entonces, ¿qué sucede cuando se usa en otras conchas?
Maythux
zsh admite &>.... @Maythux En shells que no son compatibles, &>por ejemplo dash, debe utilizar la >file 2>&1redirección trivial ..
heemayl
Entonces, ¿cuál usar si quiero estar seguro de que mi script será compatible con diferentes shells
Maythux
3
@Maythux Use >file 2>&1. Este trabajo en todos los proyectiles
Sergiy Kolodyazhnyy
1
Los shells @ TSJNachos117 configurados /etc/passwdpara cada usuario son shells interactivos. Los scripts del sistema generalmente son para, a dash menos que se especifique lo contrario En cuanto a lo que está predeterminado, está determinado por lo que está vinculado a /bin/shEn el caso de Ubuntu que es dash. En RHEL es bash, en FreeBSD es tcsh fuente y otra fuente
Sergiy Kolodyazhnyy
7

En general, recomendaría seguir la forma de hacer las cosas de Bourne-SHell , ya que bash es posiblemente el shell de Unix más popular que existe. Bash generalmente usa &>o 2>&1. En mi humilde opinión, ninguno de los dos es "perfecto", así que recomiendo olvidarse de esas tonterías. Siendo realistas, cuál debe usar depende de lo que esté tratando de hacer.

2>&1combina stderr con stdout, lo que puede ser útil si, por ejemplo, desea canalizar texto stderr. Entonces, por ejemplo, si desea ver si un programa imprime un determinado mensaje stderr, pero no desea que su pantalla se llene de basura (presumiblemente) sin importancia, puede hacer algo como program 2>&1 | grep crashed, que buscará stdout y stderr desde un programa llamado "programa" para la palabra "bloqueado".

Por otro lado, si no desea que un programa imprima nada, simplemente puede ejecutar program &> /dev/null, lo que redirigirá tanto stderr como stdout a / dev / null, un archivo especial que mágicamente hace que las cosas desaparezcan. O, si desea guardar la salida de un programa (tal vez para informar un error o algo), puede redirigir tanto stderr como stdout a un archivo: program &> log.txtredirigirá todos los datos a un archivo llamado "log.txt". Si lo desea, puede redirigir stdout y stderr a través de program 2> log.txt > log.txto program 2>&1 | cat > log.txt, los cuales tendrían el mismo efecto que usar &>. Si hace algo así program 2>&1 > file, solo se redireccionará stdout, pero stderr aún se puede canalizar a otro programa, como cat, que podría redirigirse como se muestra arriba. Sin embargo, escribiendo&>es más fácil que cualquiera de los ejemplos anteriores, ya que implica escribir menos caracteres (y es un poco más fácil de leer para los seres humanos). Tenga en cuenta que program 2> log.txt > log.txtpodría ser más probable que funcione en shells que no sean bash.

PD: si te preocupa que las personas usen otros shells, hay algo que puedes agregar a la primera línea de tu script llamado "número mágico" o "shebang". Esta es esencialmente una forma de asegurarse de que otras computadoras (particularmente aquellas que ejecutan sistemas operativos tipo Unix) sepan qué programa usar para ejecutar un script. Diferentes scripts usan diferentes shebangs. Un shebang para un script bash se ve así:

#!/bin/bash

Si usa lo anterior como la primera línea de un script dado, bash generalmente se usará para ejecutar dicho script. Esto hará que sea mucho más difícil para alguien ejecutar accidentalmente el script con el shell incorrecto.

PD: No voy a mentir: hasta ahora, no sabía que se podía usar >&, pero, en lo que respecta a bash, parece hacer lo mismo &>. Tu aprendes algo nuevo cada dia.

TSJNachos117
fuente
Si bien estoy de acuerdo con usted sobre el uso de la #!línea para solicitarlo explícitamente bash, no siempre está disponible en otros sistemas. Muy a menudo, los desarrolladores / administradores de sistemas tienen que escribir scripts portátiles para sistemas en los que bashpuede que no estén disponibles y que su instalación no esté bajo su control bash. El >file 2>&1es mucho más portátil.
Sergiy Kolodyazhnyy
Cometió un error de reversión arriba, que no produce el resultado que reclama o desea. Redirigir stderr a stdout, luego redirigir stdout deja stderr en el stdout original.
ubfan1
Serg: No quise decir que bash fuera universal. Sin embargo, creo que más personas lo están usando que decir (t) csh. Si no sabe lo que está usando otra persona y tiene que hacer una suposición ciega, bash es probablemente su mejor opción. Además, generalmente no sé sobre portabilidad, ya que solo uso bash. >file 2>&1Es bueno saber que es más portátil. Haré una edición para reflejar eso.
TSJNachos117
Ubfan1, gracias por la información. Nunca habría adivinado en un millón de años que bash no redirigiría stderr a un archivo en ese caso. Acabo de editar mi respuesta para evitar que otros cometan el mismo error.
TSJNachos117
4

Desde el Manual de referencia de Bash -> 3.6.4 Redirección de salida estándar y error estándar :

Esta construcción permite que tanto la salida estándar (descriptor de archivo 1) como la salida de error estándar (descriptor de archivo 2) se redirijan al archivo cuyo nombre es la expansión de la palabra.

Hay dos formatos para redirigir la salida estándar y el error estándar:

&>word

y

>&word

De las dos formas, se prefiere la primera. Esto es semánticamente equivalente a

>word 2>&1

Cuando se usa la segunda forma, la palabra no puede expandirse a un número o '-'. Si lo hace, se aplican otros operadores de redireccionamiento (consulte Duplicar descriptores de archivo a continuación) por razones de compatibilidad.

También es bueno consultar el wiki de Greg sobre Entrada y Salida -> 4.2. Manipulación del descriptor de archivo :

Para su comodidad, Bash también pone a su disposición otra forma de redireccionamiento. El operador de redirección &> es en realidad una versión más corta de lo que hicimos aquí [ 2>&1]; redirigiendo tanto stdout como stderr a un archivo.

fedorqui
fuente
4

Entonces, ¿por qué debo usar &> y no 2> & 1

2>&1 es el estándar Bourne / POSIX shell.

&>es una extensión bash y no estándar de jure .

Si escribes scripts usando extensiones bash, tarde o temprano te encontrarás con fallas que te rascarán la cabeza con mensajes de error de sintaxis críptica porque se ejecutan en un shell estándar.

Stephen M. Webb
fuente