Redirecionamento de E/S (Entrada/Saída) é um dos recursos mais poderosos do shell Linux/Bash. Ele permite controlar de onde um comando lê dados (entrada) e para onde ele escreve sua saída (resultados e erros). Compreender esse mecanismo é essencial para criar scripts eficientes, automatizar tarefas e lidar com logs e mensagens de erro de forma granular.

No Linux, tudo é tratado como arquivo, e os fluxos de E/S são identificados por números chamados descritores de arquivo. Os três principais são: 0 (entrada padrão), 1 (saída padrão) e 2 (saída de erro padrão). O shell oferece operadores especiais para redirecionar esses fluxos para arquivos, dispositivos ou até mesmo para outros comandos.

stdin, stdout, stderr

Cada processo no Linux possui três fluxos de E/S padrão. O stdin (descritor 0) é a entrada padrão, normalmente associada ao teclado. O stdout (descritor 1) é a saída padrão, onde os resultados normais do comando são enviados, geralmente para o terminal. O stderr (descritor 2) é a saída de erro padrão, usada para mensagens de erro e diagnóstico, também por padrão direcionada ao terminal.

Essa separação permite que você redirecione apenas a saída normal para um arquivo, enquanto os erros continuam sendo exibidos na tela, ou vice-versa. Por exemplo, ao executar um comando que pode gerar erros, você pode salvar os erros em um arquivo separado para análise posterior, sem misturá-los com a saída normal.

# Exemplo: listar arquivos e redirecionar stdout para um arquivo
ls -l > lista.txt
# O stdout (lista) vai para o arquivo; erros (ex: diretório inexistente) vão para o terminal

# Redirecionar stderr para um arquivo
ls /diretorio_inexistente 2> erros.txt

> e >>

O operador > redireciona a saída padrão (stdout) para um arquivo, sobrescrevendo o conteúdo existente. Se o arquivo não existir, ele é criado. Já o operador >> redireciona a saída padrão para um arquivo, mas adiciona ao final do arquivo (append), preservando o conteúdo anterior.

Esses operadores são amplamente usados para salvar resultados de comandos, criar logs e gerar relatórios. É importante lembrar que, por padrão, eles atuam apenas sobre o stdout. Para redirecionar stderr, é necessário especificar o descritor (2> ou 2>>).

# Sobrescrever arquivo com a saída do comando
echo "Novo conteúdo" > arquivo.txt

# Adicionar ao final do arquivo
echo "Mais conteúdo" >> arquivo.txt

# Exemplo com data: adicionar timestamp a um log
date >> log.txt

2> e &>

O operador 2> redireciona o stderr (descritor 2) para um arquivo, sobrescrevendo. Para adicionar (append) ao arquivo, use 2>>. Já o operador &> redireciona tanto stdout quanto stderr para um mesmo arquivo (ou dispositivo). É uma forma concisa de mesclar os dois fluxos.

Existem também variações como > arquivo 2>&1, que primeiro redireciona stdout para o arquivo e depois faz o stderr apontar para o mesmo destino de stdout. O &> é um atalho para isso no Bash. Dominar esses redirecionamentos é crucial para lidar com erros em scripts e para criar logs completos.

# Redirecionar apenas erros para um arquivo
comando_que_pode_falhar 2> erros.log

# Redirecionar stdout e stderr para o mesmo arquivo (sobrescrevendo)
comando &> tudo.log

# Equivalente usando descritores
comando > tudo.log 2>&1

# Adicionar ambos ao final de um arquivo
comando >> tudo.log 2>&1

/dev/null

/dev/null é um dispositivo especial no Linux que funciona como um "buraco negro": tudo que é enviado para ele é descartado. É útil quando você não quer ver a saída de um comando, nem erros, e não deseja armazená-los em arquivo. Por exemplo, para silenciar completamente um comando, redirecione stdout e stderr para /dev/null.

Outro uso comum é em scripts que verificam a existência de um arquivo: você pode redirecionar erros para /dev/null para evitar mensagens indesejadas. Também é usado para descartar saídas de comandos que você só quer executar pelo efeito colateral (como criar diretórios).

# Descartar toda a saída (stdout e stderr)
comando &> /dev/null

# Verificar se um arquivo existe sem exibir erros
if ls /arquivo_inexistente 2> /dev/null; then
    echo "Arquivo existe"
else
    echo "Arquivo não existe"
fi

# Descartar apenas a saída normal, mas ver erros
comando > /dev/null

Boas Práticas e Observações Finais

Ao usar redirecionamento, lembre-se de que a ordem importa. Por exemplo, 2>&1 > arquivo redireciona stderr para o stdout atual (que ainda é o terminal), e depois redireciona stdout para o arquivo, então os erros ainda vão para o terminal. A forma correta é > arquivo 2>&1 ou usar &>.

Outra dica: em scripts, é comum usar exec para redirecionar todos os comandos subsequentes. Por exemplo, exec &> log.txt redireciona toda a saída do script para o arquivo. Isso simplifica o código quando muitos comandos precisam ter a saída capturada.

Por fim, lembre-se de que o redirecionamento também pode ser usado com pipes (|) para conectar a saída de um comando à entrada de outro. Essa combinação é a base do pipeline no Unix.

Referências

Exercícios

  1. Crie um comando que liste o conteúdo do diretório atual e salve a saída normal em um arquivo chamado saida.txt, mas os erros (por exemplo, se houver problemas de permissão) devem ser mostrados no terminal.

    ✓ Resposta:
    ls -l > saida.txt

    O stdout é redirecionado para o arquivo; stderr (erros) permanece no terminal.

  2. Redirecione tanto stdout quanto stderr de um comando (por exemplo, ls /etc/passwd /etc/arquivo_inexistente) para o mesmo arquivo tudo.log, sobrescrevendo o conteúdo anterior.

    ✓ Resposta:
    ls /etc/passwd /etc/arquivo_inexistente &> tudo.log

    Ou: ls /etc/passwd /etc/arquivo_inexistente > tudo.log 2>&1

  3. Adicione a data e hora atuais ao final de um arquivo de log chamado historico.log, sem sobrescrever o conteúdo existente.

    ✓ Resposta:
    date >> historico.log
  4. Execute um comando que pode gerar erros (ex: rm /arquivo_inexistente) e descarte completamente qualquer saída (stdout e stderr), sem criar nenhum arquivo.

    ✓ Resposta:
    rm /arquivo_inexistente &> /dev/null
  5. Escreva um comando que liste todos os arquivos .txt no diretório atual, redirecione apenas os erros (se houver) para um arquivo erros.txt, e mostre a saída normal no terminal.

    ✓ Resposta:
    ls *.txt 2> erros.txt

    O stdout (lista de arquivos .txt) vai para o terminal; stderr (se não houver arquivos .txt ou problemas de permissão) vai para erros.txt.