você está aqui: Home  → Arquivo de Mensagens

Redirecionamentos - Parte 2 - Redirecionamento da saída primária (StdOut)

Colaboração: Julio Cezar Neves

Data de Publicação: 02 de outubro de 2019

Um lembrete, as inscrições para o curso Programação Shell Linux estão abertas, mas apenas até a próxima segunda-feira, às 23h59m. No dia 8 de outubro começamos a pleno vapor. É a última turma deste ano. Para saber mais, clique aqui.


Prá começar com o pé esquerdo, note que quando o Shell examina uma linha de comandos, se não for uma atribuição, a primeira coisa que ele fará são os redirecionamentos. Tenha isso sempre em vista!

Por exemplo, se você fizer:

$ echo Seu nome > arq
$ cat arq
Seu nome
$ cat arq > arq
$ cat arq
$

Dentro de arq não havia nada porque a primeira coisa que o Shell fez, foi criar um arquivo arq vazio para receber a saída do comando (e ele não tem a menor ideia do que o cat faz).

Assim sendo, se você quiser engordar arq com mais dados, você deverá fazer:

 echo mais dados >> arq

Parece ate piada, mas 90% das pessoas criam arquivos usando o comando touch. Isso é infinitamente mais lento que simplesmente usar um redirecionamento de entrada para criá-lo.

O comando touch é para trabalhar o timestamp dos arquivos. Para criar ARQ vazio faça:

 > ARQ

Vou criar 200 vezes o arquivo Lixo usando o comando touch e medir o tempo:

time for ((i=1; i<200; i++))
{
    touch Lixo
}
real	0m0.145s
user	0m0.016s
sys	0m0.020s

Agora vou fazer o mesmo usando o redirecionamento da saída (>):

time for ((i=1; i<200; i++))
{
    > Lixo
}
real	0m0.008s
user	0m0.008s
sys	0m0.000s

Como dá para notar, é muuuito mais rápido.

Como nós já vimos, o operador FD1&>FD2 que também pode ser FD1>&FD2 associa a saída do file descriptor FD1 à do file descriptor FD2. Então quando você deseja mandar a saída primária e a de erros do programa PRG para /dev/null, por exemplo, você deve fazer:

PRG > /dev/null 2>&1

Onde 1 é o file descriptor da entrada primária (não esqueça que > é o mesmo que 1>) e 2 é o file descriptor da saída de erros. Dessa forma, você associa a saída de erros ao mesmo descritor da saída primária que foi ligada a /dev/null.

Mas veja isso:

 ls NaoExiste
ls: não é possível acessar 'NaoExiste': Arquivo ou diretório não encontrado

O que eu teria de fazer para pegar somente o pedaço da mensagem de erros compreendida entre os dois dois pontos (:)?

Vamos tentar:

ls NaoExiste | cut -f2 -d:
ls: não é possível acessar 'NaoExiste': Arquivo ou diretório não encontrado

Não funcionou porque o cut atuou na saída primária (que estava vazia) e deveria ter atuado na saída de erros. Temos 2 formas de resolver isso:

1. Associar a saída de erros à saída primária que por default já vem associada ao terminal via /dev/pts/1 e então cortar o que interessa:

ls NaoExiste 2>&1 | cut -f2 -d:
não é possível acessar 'NaoExiste'

2. Mandar ambas as saídas para o cut:

 ls NaoExiste |& cut -f2 -d:
não é possível acessar 'NaoExiste'

O problema dessa segunda forma de redirecionamento é que o cut está atuando em ambas as saídas (primária e de erros). No nosso exemplo, sabíamos de antemão que não havia nada para a saída primária, mas se houvesse, o cut poderia gerar um resultado indesejável.

A ordem que você declara os redirecionadores é fundamental. Veja esses 2 casos a seguir:

 ls NaoExiste >x 2>&1; echo Saida = $(cat x)
Saida = ls: não é possível acessar 'NaoExiste': Arquivo ou diretório não encontrado

Aqui correu tudo bem. O erro foi redirecionado para o arquivo x, que foi listado.

 ls NaoExiste 2>&1 >x; echo Saida = $(cat x)
ls: não é possível acessar 'NaoExiste': Arquivo ou diretório não encontrado
Saida =

Assim não funcionou, porque a saída de erros foi associada ao file descriptor 1 que por padrão é o /dev/tty e caso o NaoExiste existisse, seu nome iria para o arquivo x que foi associado à saída primária.



Veja a relação completa dos artigos de Julio Cezar Neves