No mundo da interface de linha de comandos, os programas interagem frequentemente com três fluxos de dados padrão:
stdin): onde um programa recebe a sua entrada (normalmente a partir do teclado).stdout): onde um programa envia a sua saída normal (normalmente para o ecrã do terminal).stderr): onde um programa envia as mensagens de erro (normalmente para o ecrã do terminal).Recorda-te de que os apresentámos no capítulo Pipelines e Listas de Comandos.
As pipelines podem ser consideradas uma forma de redirecionamento: a saída padrão de um programa é enviada diretamente para a entrada padrão de outro. Já abordámos as pipelines. Este conceito vai abordar o redirecionamento de e para ficheiros.
O redirecionamento da shell é um mecanismo poderoso que te permite alterar o destino destes fluxos. Em vez de um programa ler do teclado ou escrever para o ecrã, podes redirecionar a entrada a partir de um ficheiro ou enviar a saída para um ficheiro. Isto dá-te bastante flexibilidade e controlo sobre a forma como os programas interagem com os dados.
Eis os operadores de redirecionamento mais comuns e o que fazem:
> (Redirecionamento de Saída)Objetivo: redirecionar a saída padrão (stdout) de um comando para um ficheiro.
Comportamento:
Exemplo:
# Sends the output of 'ls -l' to 'file_listing.txt'
ls -l > file_listing.txt
O redirecionamento é feito antes de o comando ser executado. Isto significa que não podes redirecionar para o mesmo ficheiro de onde precisas de ler.
date > date.txt # populate the file with the current date
cat date.txt > date.txt # 'date.txt' is now empty!
No segundo comando do exemplo acima,
>> (Redirecionamento de Saída com Acréscimo)Objetivo: acrescentar a saída padrão (stdout) de um comando a um ficheiro.
Comportamento:
Exemplo:
# Adds "Another line" to the end of the file
echo "Another line" >> file_listing.txt
< (Redirecionamento de Entrada)Objetivo: redirecionar a entrada padrão (stdin) de um comando a partir de um ficheiro.
Comportamento: o comando lê a sua entrada a partir do ficheiro indicado em vez do teclado.
Exemplo:
# 'tr' reads from 'lowercase.txt' and
# output is redirected to 'uppercase.txt'
tr 'a-z' 'A-Z' < lowercase.txt > uppercase.txt
2> (Redirecionamento de Erros):stderr) de um comando para um ficheiro.# Error message from 'rm' is sent to 'error_log.txt'
rm non_existent_file 2> error_log.txt
Podes acrescentar o erro padrão a um ficheiro com 2>>.
Existem também redirecionamentos que podem combinar stdin e stderr.
Consulta o manual para mais detalhes.
/dev/null/dev/null é um ficheiro especial que
Por vezes é também chamado de «the bitbucket». É útil para suprimir a saída ou os erros.
some_command > /dev/null # Discards stdout
some_command 2> /dev/null # Discards stderr
# Using /dev/null as input will prevent the command
# from reading data from the keyboard
some_command < /dev/null
Podem indicar-se vários redirecionamentos ao mesmo tempo.
some_command < input.txt > output.txt 2> error.txt
Um redirecionamento pode ser copiado.
# send stderr to the same destination as stdout
some_command > output.txt 2>&1
Quando vês 2>&1, lê isso como «redireciona o stderr para aquilo para onde o stdout está neste momento a apontar».
O Bash processa as instruções de redirecionamento estritamente da esquerda para a direita, o que significa que podes fazer:
# redirect stdout to 'output1.txt'
# redirect stderr to the same place
# then change stdout to 'output2.txt'
some_command > output1.txt 2>&1 > output2.txt
No contexto da programação de shell e de sistemas operativos como Linux/Unix, um descritor de ficheiro (FD, do inglês file descriptor) é um número inteiro não negativo que serve como identificador ou referência para um ficheiro aberto ou um recurso de E/S (Entrada/Saída). Pensa nisso como uma etiqueta ou um número de referência que o sistema operativo usa para acompanhar os ficheiros abertos e os fluxos de dados.
Os números que vês à esquerda dos redirecionamentos são descritores de ficheiro.
Os fluxos de E/S padrão recebem os primeiros três descritores de ficheiro:
Podem definir-se ou criar-se novos descritores de ficheiro com o comando exec e os operadores de redirecionamento.
# create FD 3 as a copy of stdout
exec 3>&1
# send stdout to a log file
exec > log.txt
# then redirect both stdout and file descriptor 3
echo "some debug message" >&3 # displayed in the terminal
some_command 2>&1 # stdout and stderr send to 'log.txt'
Esta técnica parece bastante complicada, mas pode ser muito útil em situações em que o teu script está a ser executado por outro pacote de software e a saída padrão é capturada automaticamente por esse software.
O comando bats que é usado para correr os testes unitários deste track funciona assim: o bats captura o stdout e o stderr de um teste, mas as mensagens de depuração enviadas para o FD 3 são apresentadas no terminal.
Porque é que o redirecionamento é útil?
Os redirecionamentos da shell dão-te um controlo preciso sobre a forma como os programas interagem com os dados, permitindo-te construir fluxos de trabalho complexos e gerir a informação de forma eficaz.