Eu armazenei o seguinte programa em new.c
int main()
{
a;
return 0;
}
Ele retorna uma mensagem de erro. Eu quero enviar esta mensagem para um arquivo. Então eu usei o seguinte comando
gcc new.c > temp.txt
Mas ainda assim eu estava recebendo a saída no terminal. Eu estou usando o Ubuntu 13.04. Como posso fazer isso funcionar?
Respostas:
Quando você compila um programa com
gcc
, existem diferentes tipos de saída: parastdout
estderr
. Normalmente, o>
vai dirigirstdout
fluxo para um arquivo (por exemplo, o resultado de umprintf("hello world\n");
é enviado parastdout
). No entanto, ostderr
continua a ser enviado para a tela, desde que é assumido como "algo excepcional que você precisa ser informado sobre".Existe uma maneira de redirecionar o stderr para um arquivo - você faz isso com o seguinte comando (não muito intuitivo):
Onde
&>
é "shorthand" para "redirecionar tudo". Como foi apontado por @CharlesDuffy, o formato compatível com POSIX éIsso significa "compilar 'new.c' e enviar
stdout
paramyFile
. E enviastderr
(2) para o mesmo lugar questdout
(&1
= "o mesmo lugar que stdout").Você encontrará mais detalhes sobre diferentes redirecionamentos em http://tldp.org/HOWTO/Bash-Prog-Intro-HOWTO-3.html e http://mywiki.wooledge.org/BashFAQ/055
By the way, se você quiser enviar algo de dentro de seu programa especificamente para
stderr
, você pode fazer isso com o seguinteSe você incluir isso em um programa, executar o programa e enviar a saída "normal" para um arquivo, isso ainda aparecerá no console. Então, se você compilar o acima no executável
urgent
e depois digiteno console, sua saída aparecerá na tela.
fonte
>myFile 2>&1
) bem como a extensão do bash (&>
).Porque
>
redireciona apenas stdout e erros são gravados emstderr
, você precisa usar um dos seguintes:...ou...
&>
é uma extensão BASH que redireciona ambosstdout
estderr
para um arquivo; caso contrário, a abordagem mais fácil é primeiro redirecionar o stdout (>temp.txt
), e então faça stderr (FD 2) uma cópia do identificador de arquivo já redirecionado no stdout (FD 1), da seguinte forma:2>&1
.fonte
Como os outros disseram, o linux fornece dois fluxos de saída diferentes:
stdout , ou "saída padrão" é onde vai toda a saída regular.
Você pode referenciá-lo usando o descritor de arquivo
1
.stderr ou "erro padrão" é um fluxo separado para informações fora de banda.
Você pode referenciá-lo usando o descritor de arquivo
2
.Por que dois fluxos de saída diferentes? Considere um pipeline de comandos imaginários:
Agora imagine o
decrypt
comando falha e gera uma mensagem de erro. Se ele enviou essa mensagem parastdout
, ele enviaria para o tubo e, a menos que tivesse a palavra "secreto", você nunca o veria. Então você acabaria com um arquivo de saída vazio, sem ideia do que deu errado.No entanto, como o tubo captura apenas
stdout
, adecrypt
comando pode enviar seus erros parastderr
, onde eles serão exibidos no console.Você pode redirecionar
stdout
estderr
, juntos ou independentemente:Você pode redirecionar os erros para
stdout
e processá-los como se fossem saída normal:Você também pode usar uma notação "abreviada" para redirecionar ambos stdout e stderr para o mesmo arquivo:
E, finalmente, o
>
operador primeiro truncar seu arquivo de saída antes de gravar nele. Se, em vez disso, você quiser acrescentar dados para um arquivo existente, use o>>
operador:fonte
$FOO
) é uma fonte comum de erros, e demonstrá-lo nos exemplos não é tão bom. (2) O uso de nomes de variáveis maiúsculas é o principal motivo para conflitos de espaço de nomes entre ambiente e variáveis internas (maiúsculas por convenção) e variáveis locais (minúsculas por convenção). (3) Encorajar as pessoas a usar repetidamente>>
(que reabre o arquivo toda vez que é usado em um comando) ao invés de abrir um arquivo uma vez e deixando o descritor de arquivos aberto para uso por vários comandos resulta em código ineficiente.exec 4>secrets; echo "this is a secret" >&4; echo "this is another secret" >&4
exec
por simplicidade, embora na prática seja geralmente uma estratégia melhor.command₁
>
output_file
;
command₂
>>
the_same_output_file
pode ser recolhido para(
command₁
;
command₂
) >
output_file
ou{
command₁
;
command₂
; } >
output_file
(onde deve haver espaços antes e depois do{
e um;
antes de o}
).