Diferença entre 2> & -, 2> / dev / null, | &, &> / dev / null e> / dev / null 2> & 1

192

Apenas procurando a diferença entre

  • 2>&-
  • 2>/dev/null
  • |&
  • &>/dev/null
  • >/dev/null 2>&1

e sua portabilidade com non-Bourne shellscomo tcsh, mksh, etc.

Det
fonte
2
Observe que, embora o mksh suporte &>a compatibilidade do GNU bash, é altamente recomendável não usá-lo, pois a análise pode quebrar a semântica dos scripts POSIX existentes, e o mksh já o desativa no modo POSIX.
mirabilos
Eu também vi ^ /dev/nullo que isso faz?
balupton

Respostas:

241

Para o fundo:

  • um número 1 = saída padrão (ou seja, STDOUT)
  • um número 2 = erro padrão (ou seja, STDERR)
  • se um número não for fornecido explicitamente, o número 1 será assumido pelo shell (bash)

Primeiro, vamos abordar a função deles. Para referência, consulte o Advanced Bash-Scripting Guide .

Funções

2>&-

A forma geral deste é M>&-onde "M" é um número de descritor de arquivo. Isso fechará a saída para qualquer descritor de arquivo mencionado, ou seja, "M" .

2>/dev/null

A forma geral deste é M>/dev/nullonde "M" é um número de descritor de arquivo. Isso redirecionará o descritor de arquivo "M" para /dev/null.

2>&1

A forma geral deste é M>&Nonde "M" e "N" são números de descritores de arquivos. Ele combina a saída dos descritores de arquivo "M" e "N" em um único fluxo.

|&

Esta é apenas uma abreviação para 2>&1 |. Foi adicionado no Bash 4.

&>/dev/null

Esta é apenas uma abreviação para >/dev/null 2>&1. Ele redireciona o descritor de arquivo 2 (STDERR) e o descritor 1 (STDOUT) para /dev/null.

>/dev/null

Esta é apenas uma abreviação para 1>/dev/null. Ele redireciona o descritor de arquivo 1 (STDOUT) para /dev/null.

Portabilidade para não bash, tcsh, mksh, etc.

Eu não lidei muito com outras conchas fora de cshe tcsh. Minha experiência com esses 2 em comparação com os operadores de redirecionamento do bash é que o bash é superior nesse aspecto. Veja a página de manual do tcsh para mais detalhes.

Dos comandos que você perguntou sobre nenhum são suportados diretamente pelo csh / tcsh. Você precisaria usar diferentes sintaxes para construir funções semelhantes.

slm
fonte
Nós temos um vencedor. Mas, portanto, não há diferença de desempenho ou algo parecido com o 2>&-vs 2>/dev/null(exceto que alguns programas escritos "mal" não compreendem 2>&-corretamente)?
Det
3
Não deve haver diferença de desempenho.
Slm
5
&>estava presente bashdesde o início (e quebra a compatibilidade com Bourne e POSIX, pois significa algo diferente lá, embora seja improvável que seja atingido). >&e |&vem (t)csh(e é a única maneira de redirecionar o stderr). Eles estavam zshdesde o início e foram adicionados apenas recentemente a bash. Veja também rcpara operadores melhor projetados.
Stéphane Chazelas
11
Atualização: sobre o problema de desempenho, também confirmada aqui: unix.stackexchange.com/questions/163955/…
Det
11
Olá @slm, obrigado pelo contato. Estou feliz que meu repo não tenha mudado (+2-2=0). Agora, para a parte da edição, não edito muito, mas nesse caso, o faria, porque esclarece que os dados após a operação estariam em N. Eu li sua resposta e é muito bom em todos os aspectos. Apenas essa pequena ambiguidade me fez pensar, é por isso que a edição. Mas ok, sinta-se à vontade para adicioná-lo novamente ou rejeitá-lo, como quiser. Espero poder explicar o ponto. Mantenha o bom trabalho.
Dr Beco
11

Isso é para redirecionar o STDERR & STDOUT:

  • 2>/dev/null

    Redirecione STDERR para / dev / null (impedir que apareça no console)

  • |&

    Redirecione STDERR e STDOUT para STDIN do comando canalizado (cmd1 | & cmd2)

  • &>/dev/null

    Redirecione STDERR e STDOUT para / dev / null (nada aparece no console)

  • >/dev/null

    Redirecione STDOUT para / dev / null (apenas STDERR é exibido no console)

  • 2>&-

    É para fechar um descritor de arquivo usado com redirecionamento

Todos esses são métodos de redirecionamento padrão para os shells Bourne.

BriGuy
fonte
4
|&e não&>/dev/null são portáteis.
Chris Baixo
4

Considere isso um adendo à resposta selecionada. Você pode querer saber quais formulários são POSIX e quais não são.

Dois formulários POSIX estão envolvidos:

2.7.2 Redirecionando a saída

Os dois formatos gerais para redirecionar a saída são:

[n]> palavra

[n]> | palavra

onde o n opcional representa o número do descritor de arquivo. Se o número for omitido, o redirecionamento deverá se referir à saída padrão (descritor de arquivo 1).

O redirecionamento de saída usando o formato '>' falhará se a opção noclobber estiver configurada (consulte a descrição do conjunto -C) e o arquivo nomeado pela expansão da palavra existir e for um arquivo regular. Caso contrário, redirecione usando '>' ou "> |" Os formatos devem fazer com que o arquivo cujo nome resulta da expansão da palavra seja criado e aberto para saída no descritor de arquivo designado, ou saída padrão, se nenhum for especificado. Se o arquivo não existir, ele deverá ser criado; caso contrário, ele será truncado para ser um arquivo vazio após ser aberto.

-

2.7.6 Duplicando um descritor de arquivo de saída

O operador de redirecionamento:

[n]> & palavra

duplicará um descritor de arquivo de saída de outro ou fechará um. Se a palavra for avaliada em um ou mais dígitos, o descritor de arquivo indicado por n, ou a saída padrão, se n não for especificado, deverá ser uma cópia do descritor de arquivo indicado por palavra; se os dígitos no word não representam um descritor de arquivo já aberto para saída, um erro de redirecionamento deve ocorrer; consulte Consequências dos erros do shell. Se a palavra for avaliada como '-', o descritor de arquivo n ou a saída padrão se n não for especificado, será fechado. Tentativas de fechar um descritor de arquivo que não está aberto não devem constituir um erro. Se a palavra for avaliada para outra coisa, o comportamento não será especificado.

Portanto:

Function      POSIX-compat    POSIX 
2>&-          Yes             close 
2>/dev/null   Yes             redir
2>&1          Yes             dup 
|&            No              
&>/dev/null   No
>/dev/null    Yes             redir
>&/dev/null   ?               ?dup

A última linha não está na pergunta original, mas funciona sem reclamação no bash. (Também funciona com / dev / tty substituído por / dev / null).

Craig Hicks
fonte
11
Eu sempre quero saber mais.
Det