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