Usando pipes e redirecionamentos no linux
Autor: Felipe Santos | Publicado: 2012-10-31T04:28:00-07:00



Uma das características mais interessantes de sistemas baseados em Unix, como o linux, é a possibilidade de juntar diversos comandos em um só e poder enviar a saída para um arquivo. Vamos aprender a fazer isso usando pipes e redirecionamentos.
Entre as características do linux, talvez a mais interessante seja a noção de que tudo é um arquivo. Até mesmo dispositivos de hardware são encarados pelo sistema como sendo arquivos.

Da mesma forma, saídas e entradas de programas de modo texto também são vistos como arquivos.

Quando um programa é iniciado, o shell (no nosso caso o bash) coloca a sua disposição arquivos especiais, o chamado Standard Input/Output ou stdio, em português entrada e saída padrão.

Standard I/O
O stdio é formado por três arquivos especiais, são eles:

Standard Input (stdin) – Este arquivo descreve o local de onde o programa vai ler a entrada de dados, geralmente é associado ao teclado.

Standard Output (stdout) – É o local para onde o programa vai enviar a saída (informações, mensagens de sucesso, etc.), quase sempre é o terminal onde o programa foi iniciado.

Standard Error (stderr) – Funciona basicamente da mesma forma que o stdout, mas é exclusivo para a saída de mensagens de erro. Também é geralmente associada ao terminal.

Stdout e stderr são separados porque é comum que as mensagens de erro sejam processadas de maneira diferente das mensagens comuns.

Pipes
Como vimos acima, tudo no linux é visto como sendo um arquivo, inclusive a saída e entrada de dados de programas. Usando essa idéia, podemos juntar diversos comandos por meio de um pipe (em portugês algo como “cano” ou “tubo”), passando a saída de um comando para a entrada de outro. Isso facilita muito o trabalho e pode agilizar tarefas que, sem isso seriam praticamente impossíveis ou pelo menos impraticáveis.

Vamos a um exemplo:

Digamos que você queira analisar as mensagens de inicialização da sua máquina em um paginador, como o less. Você faria assim:

[root@MadMax] # dmesg | less

Dessa forma, o comando dmesg envia sua saída para a entrada do comando less.

Outro exemplo:

[root@MadMax] # ps aux | grep httpd

Com esse comando você exibe na tela todos os processos do httpd (servidor web) ativos na sua máquina.

E se você quisesse somente os PIDs? Simples:

[root@MadMax] # ps aux | grep httpd | awk {'print $2'}

Bom, estes são exemplos simples, mas a partir do momento que você se acostumar com a idéia, vai achar diversas funções para isso.

Este processo é gerenciado pelo shell e é transparente para o usuário.

Redirecionamentos
Às vezes é extremamente interessante enviar a saída de um comando para um arquivo, para poder analisar posteriormente. Isso é feito usando redirecionamentos.

Um exemplo:

[root@MadMax] # ls -la &gt; file1

dessa forma, a listagem do diretório vai ser gravada em um arquivo, ao invés de ser exibida na tela.

o redirecionador ‘&gt;’ cria um arquivo novo vazio e sobrescreve o arquivo se ele já existir, para adicionar o texto no final de um arquivo existente, use ‘&gt;&gt;’

[root@MadMax] # ls -la &gt;&gt; file1

a listagem será salva no final do arquivo ‘file1′. Se o arquivo não existir, será criado.

Note que o redirecionador ‘&gt;’ envia apenas stdout, para enviar stderr, usamos ’2&gt;’.

É importante saber que o shell vai criar o arquivo antes de executar o comando, ou seja, os pipes e redirecionamentos são analisados antes da execução dos comandos. Por isso temos que tomar cuidado com comandos como esse:

[root@MadMax] # grep 'felipe' arquivo &gt; arquivo

isto nunca deve ser feito, pois o arquivo seria sobreposto por um arquivo vazio, resultando na perda de tudo que havia no arquivo. O correto seria usar um arquivo intermediário para guardar a saída do grep e depois renomeá-lo:

[root@MadMax] # grep 'felipe' arquivo &gt; arquivo2

[root@MadMax] # mv arquivo2 arquivo

Estes são os redirecionadores usados no bash, outros shells podem ter sintaxes bem diferentes.

Da mesma forma, podemos ler a entrada de um comando de um arquivo:

[user@MadMax] $ mail -s "novo arquivo" felipe &lt; novoarquivo

Assim o conteúdo do arquivo novoarquivo é enviado para o usuário felipe por email. Normalmente o comando mail espera que você digite a mensagem no terminal.

Os redirecionadores e seus significados:
cmd &gt; arquivo e

cmd 1&gt; arquivo – envia stdout para arquivo

cmd 2&gt; arquivo – envia stderr para arquivo

cmd &gt; arquivo 2&gt;&amp;1 – envia stdout e stderr para arquivo

cmd &gt; arquivo1 2&gt; arquivo2 – envia stdout para arquivo1 e stderr para arquivo2

cmd &lt; arquivo – recebe stdin de arquivo

cmd &gt;&gt; arquivo e

cmd 1&gt;&gt; arquivo – adiciona stdout ao final de arquivo

cmd 2&gt;&gt; arquivo – adiciona stderr ao final de arquivo

cmd &gt;&gt; arquivo 2&gt;&amp;1 – adiciona stdout e stderr ao final de arquivo

cdm1 | cmd2 – Envia stdout de cmd1 para cmd2

cmd1 2&gt;&amp;1 | cmd2 – Envia stdout e stderr de cmd1 para cmd2


(http://brunotorres.net/pipes-redirecionamentos)