Quais são as diferenças entre &> e 2> & 1

30

Existem duas formas de redirecionamento da saída padrão e erro padrão na saída padrão . Mas qual é o melhor? e por que o &>é considerado o perfeito?

Não consigo encontrar as diferenças, de modo que muitos tutoriais e até o manual do bash afirmam que &>é melhor!

Então, por que devo usar &>e não2>&1

Principalmente usando bashshell


EDIT: Obrigado por comentaristas

Somente> & funciona em csh ou tcsh

No ksh, apenas 2> & 1 funcionam.

uso de traço> arquivo 2> e apenas 1 redirecionamento

Então, qual usar para garantir que meu script seja compatível com outros sistemas, quaisquer que sejam os shells usados!

Maythux
fonte
o melhor é o que faz o que você precisa fazer. estes fazem coisas muito diferentes. qual shell você está usando?
Skaperen
@Skaperen usando bash
Maythux
1
o que você quer realizar?
Skaperen
Eu só quero saber qual é a diferença, que eu quero é não tanto, mas eu só preciso saber se a uma diferença de modo que uma vez que é preffred sobre os outros
Maythux
2
&> somewhereé uma abreviação apenas o bash para > somewhere 2>&1: nas palavras do manual do bash, eles são "symantically equivalente"
steeldriver

Respostas:

23

A página de manual do Bash menciona que há duas maneiras de redirecionar stderr e stdout : &> file e >& file. Agora, observe que diz stderr e stdout.

Nesse caso >file 2>&1, estamos fazendo o redirecionamento do stdout (1) para o arquivo, mas também solicitando que o stderr (2) seja redirecionado para o mesmo local que o stdout! Portanto, o objetivo pode ser o mesmo, mas a ideia é um pouco diferente. Em outras palavras "John, vá para a escola; Suzzie vá para onde John vai".

E a preferência? &>é uma bashcoisa. Portanto, se você estiver portando um script, isso não será possível. Mas se você estiver 100% certo de que seu script estará trabalhando apenas no sistema com bash - então não há preferência

Aqui está um exemplo com dasho Debian Amquist Shell, que é o padrão do 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 você pode ver, o stderr não está sendo redirecionado

Para resolver suas edições na pergunta, você pode usar a instrução if para verificar a variável $ SHELL e alterar os redirecionamentos de acordo

Mas para a maioria dos casos > file 2>&1deve funcionar


Em termos mais técnicos, o formulário [integer]>&wordé chamado Duplicating Output File Descriptor e é um recurso especificado pelo padrão POSIX Shell Command Language, suportado pela maioria dos shells compatíveis com POSIX e semelhantes ao Brourne.

Consulte também O que significa e exatamente no redirecionamento de saída?

Sergiy Kolodyazhnyy
fonte
Então, o que acontece ao usar outras conchas?
Maythux
suportes zsh &>.... @Maythux em conchas que não suportam &>por exemplo, dashvocê precisa usar o trivial >file 2>&1redirecionamento ..
heemayl
Então qual deles usar se eu quiser ter certeza meu script será compatível com escudos diferentes
Maythux
3
@Maythux Use >file 2>&1. Este trabalho em todas as conchas
Sergiy Kolodyazhnyy
1
Os shells @ TSJNachos117 definidos /etc/passwdpara cada usuário são shells interativos. Os scripts do sistema costumam dash ser, a menos que seja especificado de outra forma. Quanto ao padrão, é determinado pelo que é simbolizado /bin/shno caso do Ubuntu dash. No RHEL é bash, no FreeBSD é tcsh fonte e outra fonte
Sergiy Kolodyazhnyy 17/07/16
6

Em geral, eu recomendaria seguir a maneira de fazer as coisas do Bourne-again SHell , já que o bash é sem dúvida o shell Unix mais popular do mercado. O Bash normalmente usa &>ou 2>&1. IMHO, nem é "perfeito", então eu recomendo esquecer essa bobagem. Realisticamente, qual deles você deve usar depende do que você está tentando fazer.

2>&1mescla stderr com stdout, o que pode ser útil se, por exemplo, você desejar canalizar texto stderr. Portanto, por exemplo, se você deseja ver se um programa imprime uma determinada mensagem stderr, mas não deseja que sua tela seja preenchida com (provavelmente) lixo desnecessário, você pode fazer algo assim program 2>&1 | grep crashed, que pesquisará o stdout e o stderr em um programa chamado "programa" para a palavra "travou".

Por outro lado, se você não quer que um programa imprima nada, você pode simplesmente executar program &> /dev/null, o que redirecionará o stderr e o stdout para / dev / null, um arquivo especial que magicamente faz as coisas desaparecerem. Ou, se você deseja salvar a saída de um programa (talvez para relatar um bug ou algo assim), você pode redirecionar stderr e stdout para um arquivo: program &> log.txtredirecionará todos os dados para um arquivo chamado "log.txt". Se você quiser, poderá redirecionar o stdout e o stderr via program 2> log.txt > log.txtou program 2>&1 | cat > log.txt, ambos os quais terão o mesmo efeito que o uso &>. Se você fizer algo assim program 2>&1 > file, apenas o stdout será redirecionado, mas o stderr ainda poderá ser canalizado para outro programa, como o gato, que poderá ser redirecionado conforme mostrado acima. No entanto, digitar&>é mais fácil do que qualquer um dos exemplos acima, pois envolve a digitação de menos caracteres (e é um pouco mais fácil para os seres humanos lerem). Observe que program 2> log.txt > log.txtpode ser mais provável que funcione em shells que não sejam do bash.

PS: se você está preocupado com as pessoas que usam outras conchas, há algo que você pode adicionar à primeira linha do seu script chamada "número mágico" ou "shebang". Essa é essencialmente uma maneira de garantir que outros computadores (particularmente aqueles que executam sistemas operacionais semelhantes ao Unix) saibam qual programa usar para executar um script. Scripts diferentes usam shebangs diferentes. Um shebang para um script bash é assim:

#!/bin/bash

Se você usar o acima como a primeira linha de um determinado script, o bash geralmente será usado para executar o referido script. Isso tornará muito mais difícil para alguém executar acidentalmente o script com o shell errado.

PS: Eu não vou mentir: até agora, eu não sabia que alguém poderia usar >&, mas, no que diz respeito ao bash, parece fazer o mesmo que &>. Você aprende algo novo a cada dia.

TSJNachos117
fonte
Embora eu concorde com você sobre o uso da #!linha para solicitar explicitamente bash, ela nem sempre está disponível em outros sistemas. Muitas vezes, os desenvolvedores / administradores de sistemas precisam escrever scripts portáteis para sistemas nos quais bashpodem não estar disponíveis e pode não estar sob seu controle para instalar bash. O >file 2>&1é apenas muito portátil.
Sergiy Kolodyazhnyy 17/07/2016
Você cometeu um erro de reversão acima, que não produz o resultado que você reivindica ou deseja. Redirecione stderr para stdout e, em seguida, redirecione stdout deixa stderr no stdout original.
ubfan1
Serg: Eu não quis dizer que bash era universal. No entanto, acho que mais pessoas o estão usando do que digamos (t) csh. Se você não sabe o que alguém está usando e precisa fazer um palpite, o bash é provavelmente a sua melhor aposta. Além disso, geralmente não conheço portabilidade, pois só uso o bash. >file 2>&1É bom saber que é mais portátil. Vou fazer uma edição para refletir isso.
TSJNachos117
Ubfan1, obrigado pela informação. Eu nunca imaginaria em um milhão de anos que o bash não redirecionaria o stderr para um arquivo nesse caso. Acabei de editar minha resposta para impedir que outras pessoas cometam o mesmo erro.
TSJNachos117 23/07
4

No Manual de Referência do Bash -> 3.6.4 Redirecionando a saída padrão e o erro padrão :

Essa construção permite que a saída padrão (descritor de arquivo 1) e a saída de erro padrão (descritor de arquivo 2) sejam redirecionadas para o arquivo cujo nome é a expansão da palavra.

Existem dois formatos para redirecionar a saída padrão e o erro padrão:

&>word

e

>&word

Das duas formas, a primeira é preferida. Isso é semanticamente equivalente a

>word 2>&1

Ao usar o segundo formulário, a palavra não pode ser expandida para um número ou '-'. Caso isso aconteça, outros operadores de redirecionamento se aplicam (consulte Duplicar descritores de arquivo abaixo) por motivos de compatibilidade.

Também é bom consultar o wiki de Greg sobre Entrada e Saída -> 4.2. Manipulação de descritor de arquivo :

Por conveniência, o Bash também disponibiliza outra forma de redirecionamento. O operador de redirecionamento &> é na verdade apenas uma versão mais curta do que fizemos aqui [ 2>&1]; redirecionando stdout e stderr para um arquivo.

fedorqui
fonte
4

Então, por que devo usar &> e não 2> & 1

2>&1 é shell Bourne / POSIX padrão.

&>é uma extensão do bash e não um padrão de jure .

Se você escrever scripts usando extensões bash, mais cedo ou mais tarde, você encontrará falhas impressionantes com mensagens de erro de sintaxe enigmática, porque elas estão sendo executadas em um shell padrão.

Stephen M. Webb
fonte