Ordem dos redirecionamentos

29

Não entendo como o computador lê esse comando.

cat file1 file2 1> file.txt 2>&1

Se eu entendi, 2>&1simplesmente redirecione o Erro Padrão para a Saída Padrão.

Por essa lógica, o comando lê para mim da seguinte maneira:

  1. concatenar arquivos file1e file2.

  2. envie stdoutdesta operação para file.txt.

  3. enviar stderrpara stdout.

  4. fim?

Não tenho certeza do que o computador está fazendo. Pela minha lógica, o comando deve ser

cat file1 file2 2>&1 > file.txt

mas isso não é correto.

iDontKnowBetter
fonte

Respostas:

46

Acho mais fácil pensar em usar atribuições.

  • > é como =
  • & é como $

Você começa com

1 = /dev/tty
2 = /dev/tty

então o seu primeiro exemplo, 1> file.txt 2>&1, faz

1 = file.txt
2 = $1           # and currently $1 = file.txt

deixando você com

1 = file.txt
2 = file.txt

Se você fez o contrário, novamente começa com

1 = /dev/tty
2 = /dev/tty

então 2>&1 > file.txtfaz

2 = $1           # and currently $1 = /dev/tty
1 = file.txt

então o resultado final é

1 = file.txt
2 = /dev/tty

e você apenas redirecionou stdout, não stderr.

Mikel
fonte
Eu meio que entendo a analogia, mas é confusa - o que $significa?
Eliran Malka
Em uma tarefa como var=$othervar, $introduz o nome da variável no lado direito. Em um redirecionamento como 2>&1, &introduz o número do descritor de arquivo no lado direito. Estou dizendo que você pode pensar nisso como "arquivo 2 é igual a arquivo 1". (Mas existem dois tipos de iguais: <significa "para leitura" e >significa "para escrever".)
Mikel
12

A ordem do redirecionamento é importante e eles devem ser lidos da esquerda para a direita .

Por exemplo: command 2>&1 >somefilesignifica:

  1. Redirecione stderr(ou seja 2) para o destino atual de stdout(neste ponto, o terminal).
  2. Então mude stdout para ir para somefile.

Então, neste caso, stderrvai para o terminal e stdoutvai para um arquivo, que não é o que você provavelmente deseja.

Por outro lado, command >somefile 2>&1significa:

  1. Redirecionar stdoutparasomefile
  2. Em seguida, redirecione stderrpara o mesmo destino que stdout( somefile).

Neste último caso, ambos stderre stdoutvá para somefile, o que provavelmente é o que você deseja.

Amelio Vazquez-Reina
fonte
4
cat file1 file2 1> file.txt 2>&1

>& Na verdade, significa duplicado, ele usa a chamada de sistema dup para mapear um novo descritor de arquivo para um arquivo já aberto.

Portanto, você (na verdade o bash) deve primeiro abrir o novo stdout antes, dizendo "e redirecionar o stderr para qualquer stdout atualmente definido".

X Tian
fonte
isso é incrível! Eu estive pensando sobre isso &. você poderia incluir algumas referências a essa sintaxe ou, melhor ainda, alguns bons recursos no sistema dup acima mencionado?
Eliran Malka
1
'man dup' documenta a chamada do sistema.
X Tian
faz sentido :) thanx
Eliran Malka