Redirecionando a saída dos comandos no Bash (o essencial)

Um ponto muito importante geralmente deixado de lado são os operadores de redirecionamento, então vamos lá, o artigo vai ser pequeno, mas antes um aviso:

Esse artigo não visa explicar a parte técnica de como são contruídos, apenas como usar isso fica pra outro artigo

Sintaxe básica:

comando [operador] "caminho/para/o/arquivo.ext"

Nota:
Você pode usar dois operadores de uma vez:

comando [operador 1] "caminho/para/o/arquivo.ext" [operador 2] "caminho/para/o/arquivo.ext" 

Os operadores

Operador O que faz
> Redireciona a saída normal de um comando para o arquivo, vale notar que o conteúdo do arquivo será perdido
>> Redireciona a saída normal de um comando para o final de uma arquivo, nesse caso o conteúdo do arquivo não será perdido
2> Redireciona a saída de erro de um comando para o arquivo, vale notar que o conteúdo do arquivo será perdido
2>&1 Redireciona a saída de erro de um comando para a saída normal

Nota sobre 2>&1:


Ele não espera um arquivo, você pode usar ele assim:

 comando 2>&1

E pode, claro, combinar, com > e >>:

 comando 2>&1 >> teste

Agora você deve estar se perguntando duas coisas:

Como eu redireciono a saída de de erro para o final de um arquivo?

Então… não faço ideia usando operadores sem fazer alguma gambiarra

O que é “saída normal” e “saída de erro”?

Como eu disse, eu não vou explicar os tecniqueis mas, resumidamente:

  • Os programas do terminal geralmente escrevem no “arquivo” /dev/stdout para que o texto seja exibido, isso é chamado de “saída nomal” ou “saída padrão”

  • Porem os programas podem precisar dar alguns avisos ao usuário, ou mostrar uma mensagem de erro que poderiam atrapalhar ou serem acidentalmente, por exemplo, experimente filtrar os repositórios do sistema usando o APT:

    sudo apt update | grep "http://"
    

    Você vai receber a seguinte mensagem:

    WARNING: apt does not have a stable CLI interface. Use with caution in scripts.

    Essa é uma mensagem importante que seria perdida se fossem enviadas para a saída normal, por isso os programas colocam esse tipo de mensagem em /dev/stderr que apesar de ser chamadas de “mensagens de erro” podem ser apenas avisos ou logging

Dicas, truques e hacks

Aqui são pedaços de shell scripts ao final da série de posts você vai entender, por isso eu não vou explicar eles agora, e eles não necessariamente tratam do assunto abordado exatamente, se tem relação, eu posto

  • Criando uma função de logging:

    function log(){
      local output_file="/dev/stderr"
      [ ! "${log_file}" = "" ] && {
        output_file="${log_file}"
      }
      echo ${@} > "${outut_file}"
    }
    
  • Forçando um programa a escrever no terminal (considerando que o comando use -o para especificar o arquivo de saída):

    file_name="$(mktemp)"
    ln -fs "/dev/stdout" "${file_name}"
    
    comando -o "${file_name}" 
    

    Porque não usar “/dev/stdout”? Alguns programas bloqueiam o arquivo /dev/stdout, note que nem todo comando var responder bem a isso, o único case que eu achei útil foi na extração de arquivos

  • Impeça o operador > de sobreescrever arquivos:

    set -o noclobber 
    

    Assim se você tentar sobreescrever você vai obter uma mensagem de erro, para desfazer use: set +o noclobber

  • Inverta a saída padrão e a saída de erro:

    comando 3>&1 1>&2 2>&3 3>&-
    

E se esse artigo foi útil, considere mandar um PIX de qualquer valor para:
natanaelpix@gmail.com

15 curtidas