Neste texto são apresentados os principais conceitos associados a entradas e saídas padrão, como redirecionamentos e pipes. Também são vistos uma série de programas simples (os filtros), que podem ser muito úteis quando associados através de pipes.
A maioria dos comandos UNIX pode comunicar-se com o sistema através de descritores de arquivos especiais conhecidos como entradas e saídas padrão. Eles são:
stdin - standard input): onde o comando vai ler seus dados de entrada. No Bash, esse arquivo é referenciado pelo descritor 0.stdout - standard output): onde o comando vai escrever seus dados de saída. No Bash, esse arquivo é referenciado pelo descritor 1.stderr - standard error): onde o comando vai escrever mensagens de erro. No Bash, esse arquivo é referenciado pelo descritor 2.Quando um comando é lançado sem indicar seu arquivo de trabalho, ele busca seus dados da entrada padrão. Por default, o shell onde o comando foi lançado associa o processo ao seu terminal, ou seja: a entrada padrão do processo é associada ao teclado e as saídas padrão e de erros à tela da sessão corrente.
Um exemplo de uso da entrada e saída padrão é o comando rev, que escreve em sua saída padrão as linhas de texto lidas em sua entrada padrão, invertendo-as:
$ rev vamos fazer um teste etset mu rezaf somav * temos que achar um palindromo omordnilap mu rahca euq somet * opoetaamaateopo opoetaamaateopo * ^D $
No exemplo, as linhas marcadas com * indicam as saídas geradas pelo comando rev. O caractere ^D (Control-D) no final indica o final da entrada padrão (ou seja, o fim de arquivo). Ao receber esse caractere, o comando rev encerra sua execução, pois chegou ao final de seu arquivo de entrada (que neste caso é o teclado). Outro exemplo de uso da entrada e saída padrão é comando sort:
$ sort joao maria antonio carlos manoel ^D antonio carlos joao manoel maria $
Normalmente o shell direciona a entrada padrão para o teclado e a saída padrão para a tela da sessão do usuário, mas ele pode ser instruído para redirecioná-las para arquivos ou mesmo para outros programas, como será visto na seqüência.
O shell pode redirecionar as entrada e saídas padrão de comandos para arquivos normais no disco, usando operadores de redireção, como mostra a figura abaixo:
Os principais operadores de redireção para arquivos são:
>:$ ls > listagem.txt
<:$ rev < listagem.txt
$ rev < listagem.txt > listrev.txt
>>, como mostra o exemplo:$ ls /etc >> listagem.txt
2> (que faz referência ao descritor 2):$ ls /xpto > teste.txt ls: /xpto: No such file or directory $ ll /xpto 2> erro.txt $ cat error.txt ls: /xpto: No such file or directory
$ ll /xpto /etc/passwd > acerto.txt 2> erro.txt $ cat error.txt ls: /xpto: No such file or directory $ cat acerto.txt -rw-r--r-- 1 root root 2136 Mai 14 17:02 /etc/passwd
$ ll /xpto /etc/passwd > acerto.txt 2>&1 $ cat acerto.txt -rw-r--r-- 1 root root 2136 Mai 14 17:02 /etc/passwd ls: /xpto: No such file or directory
noclobber estiver setada através do comando set -C). Essa operação pode ser forçada através do operador !:$ ls > teste.txt teste.txt: File exists. $ ls >! teste.txt $ ls >> novo.txt novo.txt: No such file or directory $ ls >>! novo.txt
O shell permite a construção de comandos complexos através da combinação de vários comandos simples. O operador |, conhecido como pipe, ou tubo, permite conectar a saída padrão de um comando à entrada padrão de outro. Com isso, um mesmo fluxo de dados pode ser tratado por diversos comandos consecutivamente, como mostra a figura:
É importante ressaltar que os comandos conectados são lançados simultaneamente pelo shell e executam ao mesmo tempo. O shell controla a execução de cada um para que não haja acumulo de dados entre os comandos (a cada pipe é associado um buffer de tamanho limitado).
A sintaxe usada para redireção é simples. Eis alguns exemplos:
$ ls -l /etc | more $ ls -l /tmp | sort | more $ ls -l /usr/bin | cut -c31-40 | sort | more
O mecanismo de redireção de entrada/saída é genérico, ou seja, funciona para qualquer programa que use as entradas e saídas padrão, em qualquer linguagem de programação.
Um filtro é basicamente um programa que lê dados da entrada padrão, realiza algum processamento e escreve os dados resultantes na saída padrão. Um exemplo simples de filtro seria:
#include <stdio.h> #include <stdlib.h> // lê caracteres em stdin e escreve em stdout, convertendo // vogais minúsculas em '*' e vogais maiúsculas em '#'. int main () { char c ; c = getchar () ; while (c != EOF) { switch (c) { case 'a': case 'e': case 'i': case 'o': case 'u': c = '*' ; break ; case 'A': case 'E': case 'I': case 'O': case 'U': c = '#' ; break ; } putchar (c) ; c = getchar () ; } return (0); }
Para compilar esse filtro basta digitar: gcc -Wextra -o filtro filtro.c. Uma vez compilado, o arquivo executável filtro pode ser usado nas linha de comando UNIX, como qualquer outro filtro.
Existe um grande número de comandos UNIX bastante simples, cujo uso direto é pouco útil, mas que podem ser de grande valia quando associados entre si através de pipes. Esses comandos são chamados filtros, porque funcionam como filtros para o fluxo de dados. Eis alguns filtros de uso corrente:
cat : concatena diversos arquivos na saída padrãotac : idem, mas inverte a ordem das linhasmore : permite a paginação do fluxo de dadostr : troca de caracteres entre dois conjuntoshead : seleciona as n linhas iniciais do fluxo de dadostail : seleciona as n linhas finais do fluxo de dadoswc : conta o número de linhas, palavras e bytes do fluxosort : ordena as linhas segundo critérios ajustáveisuniq : remove linhas repetidas, deixando uma só linhased : para operações complexas de strings (trocas, etc)grep : seleciona linhas contendo uma determinada expressãocut : seleciona colunas do fluxo de entradarev : reverte a ordem dos caracteres de cada linha do fluxo de entradatee : duplica o fluxo de entrada (para um arquivo e para a saída standard)Para conhecer melhor cada um dos comandos acima, basta consultar suas respectivas páginas de manual.
/usr. /tmp, colocando o resultado no arquivo users-tmp.txt. Siga os seguintes passos:find para listar os proprietários de todos os arquivos dentro de /tmp (dica: use a opção -printf do comando find).sortuniqusers-tmp.txt.cat nonexistentfilefile /sbin/ifconfiggrep root /etc/passwd /etc/nofiles > grepresults/etc/init.d/sshd start > /var/tmp/output/etc/init.d/crond start > /var/tmp/output 2>&1$HOME/saida.txt e stderr para $HOME/erro.txt.$ mkdir vazio $ cd vazio $ cp a b cp: cannot stat 'a': No such file or directory $ cp a b >a
cp? Qual o conteúdo do arquivo a? $ date >a $ cat a Wed Feb 8 03:01:21 EST 2012 $ cp a b $ cat b Wed Feb 8 03:01:21 EST 2012 $ cp a b >a $ cat b
b está vazio? O que há no arquivo a?