Precedência de redirecionamento stdin e stdout no Bash

9

Minha pergunta é sobre a precedência de redirecionamento é bash. Suponha que você tenha um comando:

cmd1 < cmd2 > cmd3

Seria traduzir para:

(cmd1 < cmd2) > cmd3

Ou

cmd1 < (cmd2 > cmd3)

Deepak Mittal
fonte

Respostas:

11

O padrão POSIX especifica que o redirecionamento do shell é da esquerda para a direita; isto é, a ordem é significativa:

A construção 2>&1é frequentemente usada para redirecionar o erro padrão para o mesmo arquivo da saída padrão. Como os redirecionamentos ocorrem do começo ao fim, a ordem dos redirecionamentos é significativa. Por exemplo:

ls > foo 2>&1

direciona a saída padrão e o erro padrão para o arquivo foo. Contudo:

ls 2>&1 > foo

direciona apenas a saída padrão para o arquivo fooporque o erro padrão foi duplicado como saída padrão antes que a saída padrão fosse direcionada ao arquivo foo.

bash opera em conformidade com esta parte da norma:

$ ls doesnotexist > foo 2>&1
$ cat foo
ls: cannot access doesnotexist: No such file or directory
$ ls doesnotexist 2>&1 > foo
ls: cannot access doesnotexist: No such file or directory
$ cat foo
$ 

Quanto à tubulação:

Como a atribuição de pipeline de entrada ou saída padrão ou ambas ocorre antes do redirecionamento, ela pode ser modificada pelo redirecionamento. Por exemplo:

$ command1 2>&1 | command2

envia a saída padrão e o erro padrão de command1para a entrada padrão de command2.

Matt Eckert
fonte
Isso pressupõe que o shell Bash seja compatível com POSIX.
precisa saber é o seguinte
11
Eu não estou entendendo. Como você disse que o pedido é da esquerda para a direita, não deve ls > foo 2>&1significar redirecionar stdout para foo e depois redirecionar stderr para stdout. Portanto, isso não deve funcionar. Da mesma forma, o segundo comando deve funcionar. O que estou perdendo aqui?
Deepak Mittal
11
O @fpmurphy bashgeralmente é compatível com POSIX, exceto nas situações descritas aqui , onde o bashcomportamento padrão é diferente. Para tornar a bashconformidade mais, você pode usar a --posixopção
precisa
@dpacmittal O primeiro exemplo, ls > foo 2>&1funciona assim: primeiro, a saída padrão é redirecionada para foo, então, o erro padrão é redirecionado para a saída padrão, que agora é o arquivo foo. O segundo exemplo, ls 2>&1 > fooopera assim: o erro padrão é redirecionado para a saída padrão antes que a saída padrão seja redirecionada para foo, portanto, o erro padrão é repetido localmente em vez de ser direcionado ao arquivo.
precisa
4
@ dpacmittal .. re ls 2>&1 >foo talvez você possa pensar assim. stderr de 'ls' é redirecionado para stdout. Isso vai acontecer! Ele irá para onde o stdout está atualmente designado, independentemente de quaisquer outras diretivas relacionadas ao stdout .. (porque essa é sua diretiva prime / first ). e ele faz ... Lembre-se: stderr não é transmutado para realmente se tornar stdout .. Ele apenas vai para onde stdout foi atribuído no momento da diretiva. (por exemplo, o terminal)
Peter.O
4

Eu acho que também não. Um par de parênteses significa uma subcasca. Mas, neste caso, nenhum sub-shell será iniciado por causa do redirecionamento. Bash simplesmente alimenta cmd2stdin e alimenta stdout cmd3.

Estou pensando, você quer dizer algo assim cmd1 | cmd2 | cmd3? Porque você cmd2e cmd3normalmente são arquivos normais em vez de "cmds".

MetroWind
fonte