EDITAR

EDITAR

EDITAR

Por favor, veja não apenas a resposta aceita, mas também a(s) outra(s).

Pergunta

Por que redirecionar STDOUT e STDERR para o mesmo arquivo não funciona, embora pareça igual a 1>[FILENAME] 2>&1 ?

Aqui está um exemplo:

perl -e 'print "1\n" ; warn "2\n";' 1>a.txt 2>a.txt
cat a.txt
# outputs '1' only.

Bem por que? Achei que isso funcionava porque... STDOUT é redirecionado para a.txt e STDERR também. O que aconteceu com STDERR?

Responder1

Ambos os redirecionamentos truncam o arquivo, portanto o segundo (em ordem cronológica de execução) substituirá o primeiro. Tentar

rm a.txt ; touch a.txt ; perl -e 'print "1\n" ; warn "2\n";' 1>>a.txt 2>>a.txt

Ou apenas use o mesmo descritor de arquivo

perl -e 'print "1\n" ; warn "2\n";' 1>a.txt 2>&1

Responder2

Com 1>a.txt 2>&1, o descritor de arquivo nº 1 éduplicadopara #2. Ambos fazem referência ao mesmo "arquivo aberto" e compartilham a posição atual e o modo r/w. (Na verdade, não há diferença alguma entre usar 2>&1 e 2<&1.)

Com 1>a.txt 2>a.txt, ambos os descritores de arquivo sãoaberto de forma independentee têm posições de cursor separadas. (O arquivo também fica truncado duas vezes.) Se você escrever "Hello" no fd #1, sua posição avançará para o byte 5, mas o fd #2 permanecerá no byte 0. Imprimir no fd #2 apenas substituirá os dados começando em 0 .

É fácil ver se a segunda gravação é mais curta:

$ perl -e 'STDOUT->print("abcdefg\n"); STDOUT->flush; STDERR->print("123");' >a.txt 2>a.txt

$ cat a.txt 
123defg

Observe que Perl possui buffer interno, portanto, neste exemplo, um flush() explícito é necessário para garantir que os dados do fd #1 sejam gravados antes dos dados do fd #2. Caso contrário, os fluxos seriam liberados em uma ordem imprevisível na saída.

Para efeito de comparação, se os descritores de arquivo forem compartilhados, as gravações apenas se sucedem:

$ perl -e 'STDOUT->print("abcdefg\n"); STDOUT->flush; STDERR->print("123");' >a.txt 2>&1

$ cat a.txt 
abcdefg
123

informação relacionada