O que faz o shell interpretar esses redirecionamentos da seguinte maneira?

2

Alguém pode me ajudar a entender esse comportamento aparentemente estranho de como o shell analisa os redirecionamentos ...?

$ cat > test.txt
Line 1
Line 2
$ ls -i dummy.txt dummy2.txt
ls: dummy.txt: No such file or directory
ls: dummy2.txt: No such file or directory
$ 
$ cat test.txt > dummy.txt > dummy2.txt
$ cat dummy2.txt
Line 1
Line 2
$ cat dummy.txt
$

Interessante! Eu teria esperado que a saída de cat test.txt fosse redirecionada para dummy.txt e, em seguida, o shell leria dummy.txt como a entrada para dummy2.txt . Mas de alguma forma o shell analisa de forma diferente ...

Então, como o conteúdo de test.txt é considerado como a entrada para dummy2.txt , ignorando dummy.txt ao todo?

Nota: O mesmo resultado no bash e no ksh ..

    
por Kent Pawar 08.04.2013 / 18:46

2 respostas

4

É importante saber que seu shell não está redirecionando a saída , mas os descritores de arquivos . Todo processo em um sistema operacional compatível com POSIX possui 3 fluxos de E / S: STDIN, STDOUT e STDERR. O redirecionamento > redireciona o descritor de arquivo para o fluxo STDOUT. Então, o que a shell vê enquanto analisa essa linha é:

  1. cat test.txt - Ok, eu vou rodar o programa cat e dar o argumento test.txt
  2. > dummy.txt - Ah, agora vou pegar o descritor STDOUT do processo cat e conectá-lo a este arquivo chamado "dummy.txt". Eu não me importo se alguma coisa estava lá antes, eu vou criar o arquivo e truncá-lo para zero.
  3. > dummy2.txt - Ah, agora eu vou pegar o descritor STDOUT do processo cat (que eu conectei anteriormente a "dummy.txt") e conectá-lo a um novo arquivo diferente. Eu não posso fazer as duas coisas, porque você está redirecionando, e não dup inserindo os descritores de arquivos.

É por isso que este comando:

find / 2>&1 >/dev/null

resulta em saída de erro no STDOUT e nenhuma saída regular (STDOUT), mas esta aqui:

find / >/dev/null 2>&1

resulta em nenhuma saída. No primeiro caso, colocamos STDERR em uma cópia (dup) de STDOUT, depois colocamos o STDOUT antigo no lixo. Na segunda, primeiro colocamos o STDOUT na lixeira, depois copiamos (ainda apontamos para /dev/null ) e colocamos o STDERR lá também.

    
por 08.04.2013 / 19:38
2

Do comentário para responder, embora parte disso seja especulação:

Se você correr, no bash,

cat test.txt > d1 > d2 > d3 > d4 > d5 

então d1 a d4 estarão vazios e o conteúdo de test.txt estará em d5. O Bash parece executar o redirecionamento real apenas para o último arquivo indicado.

Curiosamente, zsh (versão 5 pelo menos) copiará o conteúdo de test.txt em todos os arquivos intermediários também.

O bash manpage indica que a ordem de redirecionamento é significativa e, portanto, parece que a última direção indicada substitui os intermediários. Mas, porque eles estão lá, o bash cria esses arquivos antes que ele perceba onde está o conteúdo real.

A parte específica da página man é a seguinte:

Note that the order of redirections is significant.  For example, the command

              ls > dirlist 2>&1

directs both standard output and standard error to the file dirlist, 
while the command

              ls 2>&1 > dirlist

directs  only the standard output to file dirlist, because the standard 
error was duplicated from the standard output before the standard output
was redirected to dirlist.

Isso não cobre especificamente a situação, mas indica que o pedido é importante. Como tal, ver um comportamento estranho ao fazer coisas estranhas (repetidamente redirecionando o stdout para lugares diferentes) pode ter resultados surpreendentes.

Tenho certeza de que alguém estará junto em breve para corrigir qualquer erro selvagem (ou leve) nesta especulação: -)

    
por 08.04.2013 / 19:34