Aprenda Linux, 101: Fluxos, canais e redirecionadores

Familiarizando-se com instalações Linux

Se você acredita que fluxos e canais fazem um especialista em Linux® parecer um instalador, eis a sua chance de aprender sobre eles e saber como redirecioná-los e dividi-los. Você até aprenderá como transformar um fluxo em argumentos de comando. O material desse artigo pode ser utilizado com o intuito de estudar para o exame LPI® 101 para certificação de administrador de sistema Linux, ou apenas para aprender.

Ian Shields, Senior Programmer, IBM

Ian ShieldsIan Shields trabalha em vários dos projetos Linux para a zona Linux do developerWorks. Ele é um programador senior da IBM em Research Triangle Park, NC. Ele iniciou na IBM em Canberra, Austrália, como um Engenheiro de Sistemas em 1973 e, desde então, trabalhou em sistemas de comunicações e computação disseminada em Montreal, no Canadá, e em RTP na Carolina do Norte, nos Estados Unidos. Ele possui diversas patentes. Sua graduação é em matemática pura e filosofia na Australian National University. Ele possui mestrado em ciências e é doutor em ciências da computação na Universidade do Estado da Carolina do Norte.



11/Nov/2009

Sobre esta série

Esta série de artigos ajuda a aprender sobre tarefas de administração do sistema Linux. O material desses artigos também pode ser utilizado para preparação para Linux Professional Institute Certification level 1 (LPIC-1) exams.

Consulte nosso series roadmap para descrição e link de cada artigo nesta série. O roteiro está em andamento e reflete os recentes (abril de 2009) objetivos para os exames LPIC-1: assim que concluirmos os artigos, eles serão adicionados ao roteiro. Enquanto isso, é possível encontrar versões mais recentes de material similar, suportando objetivos LPIC-1 anteriores, antes de abril de 2009, em nosso LPI certification exam prep tutorials.

Pré-requisitos

Para obter o melhor dos artigos nessas séries, é necessário ter o conhecimento básico do Linux e um sistema do mesmo funcionando, no qual você pode praticar os comandos abordados neste artigo. Às vezes, versões diferentes de um programa podem formatar a saída de maneira diferente, portanto seus resultados podem não ficar exatamente parecidos com os das listagens e números mostrados aqui.

Visão geral

Este artigo apresenta as técnicas básicas de Linux para redirecionar fluxos de ES padrão. Aprenda como:

  • Redirecionar os fluxos de ES padrão: entrada padrão, saída padrão e erro padrão
  • Saída de canal de um comando para a entrada de outra
  • Envie saída para stdout e um arquivo
  • Use saídas de comandos como argumentos para outro comando

Esse artigo ajuda a se preparar para o Objetivo 103.4 no Tópico103 do exame 101 de Administração Nível Júnior do Linux Professional Institute (LPIC-1). O objetivo tem peso 4.


Configurando os exemplos

Neste artigo, praticaremos os comandos utilizando alguns dos arquivos criados no artigo "Learn Linux 101: Text streams and filters." Mas se você não leu o arquivo, ou não salvou os arquivos em que trabalhou, sem problemas! Vamos começar criando um novo subdiretório no seu diretório inicial chamado de lpi103-4 e criando os arquivos necessários dentro dele. Faça isso abrindo a janela de texto com seu diretório inicial como seu diretório atual. Então copie os conteúdos da 1 para a janela para executar os comandos que criarão o subdiretório Ipi103-4 e os arquivos que você usará.

Listagem 1. Criando os arquivos de exemplo
mkdir -p lpi103-4 && cd lpi103-4 && {
echo -e "1 apple\n2 pear\n3 banana" > text1
echo -e "9\tplum\n3\tbanana\n10\tapple" > text2
echo "This is a sentence. " !#:* !#:1->text3
split -l 2 text1
split -b 17 text2 y; }

Sua janela deve parecer-se com a da Listagem 2 e seu diretório atual deve agora ser o recentemente diretório criado Ipi103-4.

Listagem 2. Criando os arquivos de exemplo - saída

Clique aqui para ver lista de códigos

Listagem 2. Criando os arquivos de exemplo - saída

[ian@echidna ~]$ mkdir -p lpi103-4 && cd lpi103-4 && {
> echo -e "1 apple\n2 pear\n3 banana" > text1
> echo -e "9\tplum\n3\tbanana\n10\tapple" > text2

> echo "This is a sentence. " !#:* !#:1->text3echo "This is a sentence. " "This is a sentence. " "This is a sentence. ">text3
> split -l 2 text1
> split -b 17 text2 y; }
[ian@echidna lpi103-4]$

Redirecionando ES padrão

Uma shell Linux, como Bash, recebe entrada e envia saída como sequências ou fluxos de caracteres. Cada caractere é independente do que vem antes e do que vem depois dele. Os caracteres não são organizados em registros estruturados ou blocos de tamanho fixo. Fluxos são acessados utilizando técnicas de ES de arquivo, não importa se o fluxo de caracteres real vem de ou vai para um arquivo, um teclado, uma janela em um monitor ou outro dispositivo de ES. Shells Linux usam três fluxos de E/S padrão, cada um dos quais é associado com um descritor de arquivo bem conhecido:

  1. stdout é o fluxo de saída padrão, que exibe saída de comandos. Possui descritor 1 de arquivo.
  2. stderr é o fluxo de erro padrão, que exibe saída de erro de comandos. Possui descritor 2 de arquivo.
  3. stdin é o fluxo de entrada padrão, que fornece entrada para comandos. Possui descritor 0 de arquivo.

Fluxos de entrada fornecem entrada para programas, normalmente de digitações em um terminal. Fluxos de saída imprimem caracteres de texto, normalmente para o terminal. O terminal era originalmente uma máquina de escrever ASCII ou terminal de exibição, mas agora é mais frequentemente uma janela de texto em uma área de trabalho gráfica.

Se você já estudou o artigo "Learn Linux 101: Text streams and filters," parte do material neste artigo lhe será familiar.

Redirecionando a saída

Há duas maneiras de redirecionar saída para um arquivo:

n>
redireciona saída do descritor de arquivo n para um arquivo. É necessário ter autoridade de gravação para o arquivo. Se o arquivo não existir, ele é criado. Se existir, os conteúdos existentes normalmente são perdidos sem qualquer aviso.
n>>
também redireciona saída do descritor de arquivo n para um arquivo. Novamente, é necessário ter autoridade de gravação para o arquivo. Se o arquivo não existir, ele é criado. Se existir, a saída é anexada ao arquivo existente.

O n em n> ou n>> refere-se ao descritor de arquivo. Se omitido, a saída padrão é considerada. A Listagem 3 ilustra o uso de redirecionamento para separar a saída padrão e o erro padrão do comando ls utilizando arquivos criados anteriormente em nosso diretório lpi103-4. Também ilustramos o anexo da saída a arquivos existentes.

Listagem 3. Redirecionamento de saída
[ian@echidna lpi103-4]$ ls x* z*
ls: cannot access z*: No such file or directory
xaa  xab
[ian@echidna lpi103-4]$ ls x* z* >stdout.txt 2>stderr.txt
[ian@echidna lpi103-4]$ ls w* y*
ls: cannot access w*: No such file or directory
yaa  yab
[ian@echidna lpi103-4]$ ls w* y* >>stdout.txt 2>>stderr.txt

[ian@echidna lpi103-4]$ cat stdout.txt
xaa
xab
yaa
yab
[ian@echidna lpi103-4]$ cat stderr.txt
ls: cannot access z*: No such file or directory
ls: cannot access w*: No such file or directory

Dissemos que redirecionamento de saída utilizando n> normalmente substitui arquivos existentes. É possível controlar isso com a opção noclobber do builtin set. Se foi definido, é possível substituí-lo utilizando n>| como mostrado na Listagem 4.

Listagem 4. Redirecionamento de saída com noclobber
[ian@echidna lpi103-4]$ set -o noclobber
[ian@echidna lpi103-4]$ ls x* z* >stdout.txt 2>stderr.txt
-bash: stdout.txt: cannot overwrite existing file
[ian@echidna lpi103-4]$ ls x* z* >|stdout.txt 2>|stderr.txt
[ian@echidna lpi103-4]$ cat stdout.txt

xaa
xab
[ian@echidna lpi103-4]$ cat stderr.txt
ls: cannot access z*: No such file or directory
[ian@echidna lpi103-4]$ set +o noclobber #restore original noclobber setting

Às vezes você pode desejar redirecionar tanto saída padrão quanto erro padrão para um arquivo. Isso é feito frequentemente para processos automatizados ou tarefas de plano de fundo de modo que você pode revisar a saída mais tarde. Use &> ou &>> para redirecionar tanto a saída padrão quanto o erro padrão para o mesmo local. Outra maneira de fazer isso é redirecionar o descritor de arquivo n e então redirecionar o descritor de arquivo m para o mesmo local utilizando a construção m>&n ou m>>&n. A ordem na qual as saídas são redirecionadas é importante. Por exemplo,
command 2>&1 >output.txt
não é o mesmo que
command >output.txt 2>&1
No primeiro caso, o stderr é redirecionado para o local atual de stdout e então, esse é redirecionado para output.txt, mas esse segundo redirecionamento afeta somente stdout, não stderr. No segundo caso, stderr é redirecionado para o local atual de stdout, que é output.txt. Ilustramos esses redirecionamentos na Listagem 5. Observe no último comando que a saída padrão foi redirecionada depois do erro padrão, então a saída de erro padrão ainda vai para a janela do terminal.

Listagem 5. Redirecionando dois fluxos para um arquivo
[ian@echidna lpi103-4]$ ls x* z* &>output.txt
[ian@echidna lpi103-4]$ cat output.txt
ls: cannot access z*: No such file or directory
xaa
xab
[ian@echidna lpi103-4]$ ls x* z* >output.txt 2>&1
[ian@echidna lpi103-4]$ cat output.txt
ls: cannot access z*: No such file or directory
xaa
xab
[ian@echidna lpi103-4]$ ls x* z* 2>&1 >output.txt # stderr does not go to output.txt

ls: cannot access z*: No such file or directory
[ian@echidna lpi103-4]$ cat output.txt
xaa
xab

Em outras vezes, você pode desejar ignorar totalmente tanto a saída padrão quanto o erro padrão. Para fazer isso, redirecione o fluxo adequado para o arquivo vazio, /dev/null. A Listagem 6 mostra como ignorar saída de erro do comando ls, e também usar o comando cat para mostrar que /dev/null está, de fato, vazio.

Listagem6. Ignorando a saída utilizando /dev/null
[ian@echidna lpi103-4]$ ls x* z* 2>/dev/null
xaa  xab
[ian@echidna lpi103-4]$ cat /dev/null

Redirecionando a saída

Assim como podemos redirecionar fluxos stdout e stderr, também podemos redirecionar stdin de um arquivo utilizando o operador <. Se você já estudou o artigo "Learn Linux 101: Text streams and filters," você pode lembrar, da nossa discussão de sort and uniq, que utilizamos o comando tr para substituir os espaços em nosso arquivo text1 com tabulações. Nesse exemplo, utilizamos a saída de comando cat para criar uma saída padrão para o comando tr. Em vez de solicitar desnecessariamente cat, podemos agora usar redirecionamento de entrada para converter os espaços em tabulações, como mostrado na Listagem 7.

Listagem 7. Redirecionamento de entrada
[ian@echidna lpi103-4]$ tr ' ' '\t'<text1
1       apple
2       pear
3       banana

Os shells, incluindo o bash, também contam com o conceito de here-document, que é outra forma de redirecionamento de entrada. Que usa << junto com uma palavra, como END, para um marcador ou sentinela indicar a saída da entrada. Demonstramos isso na Listagem 8.

Listagem 8. Redirecionamento de entrada com um here-document
[ian@echidna lpi103-4]$ sort -k2 <<END
> 1 apple
> 2 pear
> 3 banana
> END
1 apple
3 banana
2 pear

Você pode estar pensando se não poderíamos simplesmente ter digitado sort -k2, inserido seus dados e então apertado Ctrl-d para sinalizar o final da entrada. A resposta breve é que sim, mas então você não teria aprendido sobre os here-documents. A resposta real é que os here-documents são frequentemente utilizados em scripts shell. (Um script não possui outra maneira de sinalizar quais de suas linhas devem ser tratadas como entrada). Pelo fato de os scripts shell fazerem amplo uso de tabulação para fornecer identificação para legibilidade, há outra reviravolta para os here-documents. Se você usar <<- em vez de apenas <<, então as tabulações principais são removidas.

Na Listagem 9, criamos um caractere de tabulação cativo utilizando substituição de comando e então criamos um script shell muito pequeno contendo dois comandos cat, nos quais cada um lê através de um here-document. Observe que utilizamos END como sentinela para o here-document que estamos lendo através do terminal. Se usássemos a mesma palavra para a sentinela dentro do script, terminaríamos nossa digitação prematuramente. Então use EOF, em vez disso. Depois de nosso script ser criado, utilizamos o comando . (ponto) para fazer source dele, o que significa executá-lo no contexto atual de shell.

Listagem 9. Redirecionamento de entrada com um here-document
[ian@echidna lpi103-4]$ ht=$(echo -en "\t")
[ian@echidna lpi103-4]$ cat<<END>ex-here.sh
> cat <<-EOF
> apple
> EOF

> ${ht}cat <<-EOF
> ${ht}pear
> ${ht}EOF
> END
[ian@echidna lpi103-4]$ cat ex-here.sh
cat <<-EOF
apple
EOF
        cat <<-EOF
        pear
        EOF
[ian@echidna lpi103-4]$ . ex-here.sh

apple
pear

Você aprenderá mais sobre substituição de comando e script em artigos posteriores desta série. Consulte nosso series roadmap para descrição e link de cada artigo nesta série.


Criando pipelines

No artigo "Learn Linux 101: Text streams and filters," descrevemos filtragem de texto como o processo de capturar um fluxo de entrada de texto e realizar alguma conversão no mesmo antes de enviá-lo para um fluxo de saída. Essa filtragem é feita mais frequentemente ao construir um pipeline de comandos em que a saída de um comando é canalizada ou redirecionada para ser utilizada como entrada para o próximo. Usar pipelines desta maneira não está restrito a fluxos de texto, embora seja frequentemente onde são utilizados.

Canalizando stdout para stdin

Você usa o operador | (canal) entre dois comandos para direcionar o stdout do primeiro para o stdin do segundo. Você constrói pipelines mais longos adicionando mais comandos e mais operadores de canal. Qualquer dos comandos pode ter opções ou argumentos. Muitos comandos usam um hífen (-) no lugar do nome do arquivo como um argumento para indicar quando a entrada deve vir de um stdin em vez de um arquivo. Verifique as páginas principais para o comando para ter certeza. Construir longos pipelines de comandos, sendo que cada um tenha recurso limitado é uma maneira comum de Linux e UNIX® realizarem tarefas. No pipeline hipotético utilizado na Listagem 10, command2 e command3 usam ambos parâmetros, enquanto command3 usa o apenas o parâmetro - para indicar entrada de stdin.

Listagem 10. Canalizando saída através de diversos comandos
 command1 | command2 paramater1 | command3 parameter1 - parameter2 | command4

Uma coisa a observar é que pipelines apenas canalizam stdout para stdin. Não é possível usar 2| para canalizar apenas stderr, pelo menos não com as ferramentas que aprendemos até agora. Se stderr foi redirecionado para stdout, então ambos os fluxos serão canalizados. Na Listagem 11, ilustramos um comando ls improvável com quatro argumentos principais que não estão em ordem alfabética, então utilizamos um canal para classificar as saídas de erro e normais combinadas.

Listing 11. Canalizando dois fluxos de saída
[ian@echidna lpi103-4]$ ls y* x* z* u* q*
ls: cannot access z*: No such file or directory
ls: cannot access u*: No such file or directory
ls: cannot access q*: No such file or directory
xaa  xab  yaa  yab
[ian@echidna lpi103-4]$ ls y* x* z* u* q*  2>&1 |sort
ls: cannot access q*: No such file or directory
ls: cannot access u*: No such file or directory
ls: cannot access z*: No such file or directory
xaa
xab
yaa
yab

Uma vantagem de canais em sistemas Linux e UNIX é que, diferentemente de outros sistemas operacionais populares, não há arquivo intermediário envolvido em um canal. O stdout do primeiro comando não é gravado para um arquivo e então lido pelo segundo comando. No artigo "Learn Linux 101: File and directory management," você aprenderá a arquivar e compactar um arquivo em uma etapa utilizando o comando tar. Se você estiver trabalhando em um sistema UNIX em que o comando tar não suporte compactação -z (para gzip) ou -j (para bzip2), não há problema. É possível simplesmente usar um pipeline como

bunzip2 -c somefile.tar.bz2 | tar -xvf -

para realizar a tarefa.

Iniciando pipelines com um arquivo, em vez de stdout

Nos pipelines acima, iniciamos com algum comando que gerou saída e então essa saída foi canalizada através de cada estágio do pipeline. E se quisermos iniciar com um arquivo de dados que já existe? Muitos comandos utilizam tanto o stdin quanto um arquivo como entrada, então não há problema. Se você deseja ter um filtro que requer entrada stdin, você pode considerar usar o comando cat para copiar o arquivo para o stdout, o que funcionaria. Entretanto, é possível usar redirecionamento de entrada para o primeiro comando e então canalizar a saída desse comando através do restante do pipeline para a solução mais comum. Apenas use o operador < para redirecionar o stdin do seu primeiro comando para o arquivo que deseja processar.


Utilizando saídas como argumentos

Na discussão anterior sobre pipelines, você aprendeu como capturar a saída de um comando e usá-la como entrada para outro comando. Suponha, em vez disso, que você deseja usar a saída de um comando ou os conteúdos de um arquivo como argumentos para um comando, em vez de como entrada. Pipelines não funcionam para isso. Três métodos comuns são:

  1. O comando xargs
  2. O comando find com a opção -exec
  3. Substituição de comando

Você aprenderá sobre os dois primeiros agora. Você aprendeu um exemplo de substituição de comando na Listagem 9 quando criamos um caractere de tabulação cativo. A substituição de comando é utilizada na linha de comando, mas, mais frequentemente em script; você aprenderá mais sobre isso e script em artigos posteriores a esta série. Consulte nosso series roadmap para descrição e link de cada artigo nesta série.

Utilizando o comando xargs

O comando xargs lê a entrada padrão e então cria e executa comandos com a entrada como parâmetro. Se nenhum comando for fornecido, então o comando echo é utilizado. A Listagem 12 é um exemplo básico utilizando nosso arquivo text1, que contém três linhas, cada uma com duas palavras.

Listagem 12. Utilizando xargs
[ian@echidna lpi103-4]$ cat text1
1 apple
2 pear
3 banana
[ian@echidna lpi103-4]$ xargs<text1
1 apple 2 pear 3 banana

Então por que há apenas uma linha de saída de xargs? Por padrão, xargs quebra as entradas em branco, e cada token resultante torna-se um parâmetro. Entretanto, quando xargs cria o comando, passará por vários parâmetros de uma só vez quanto forem possíveis. É possível substituir esse comportamento com o parâmetro -n ou --max-args. Na Listagem 13 ilustramos o uso de ambas as formas e adicionamos uma execução explícita de echo para nosso uso de xargs.

Listagem 13. Utilizando xargs e echo
[ian@echidna lpi103-4]$ xargs<text1 echo "args >"
args > 1 apple 2 pear 3 banana
[ian@echidna lpi103-4]$ xargs --max-args 3 <text1 echo "args >"
args > 1 apple 2
args > pear 3 banana
[ian@echidna lpi103-4]$ xargs -n 1 <text1 echo "args >"

args > 1
args > apple
args > 2
args > pear
args > 3
args > banana

Se a entrada contém espaços em branco que são protegidos por aspas simples ou duplas, ou por escape de contra barra, então xargs não quebrará a entrada nesses pontos. A Listagem 14 ilustra esse ponto.

Listagem 14. Utilizando xargs com aspas
[ian@echidna lpi103-4]$ echo '"4 plum"' | cat text1 -
1 apple
2 pear
3 banana
"4 plum"
[ian@echidna lpi103-4]$ echo '"4 plum"' | cat text1 - | xargs -n 1
1
apple
2
pear
3
banana
4 plum

Até agora, todos os argumentos foram adicionados ao final do comando. Se você necessita usá-los como argumentos com os argumentos seguintes, então use a opção -I para especificar uma cadeia de caracteres de substituição. Onde quer que a cadeia de caracteres de substituição ocorra no comando que você solicitar a execução de xargs, ele será substituído por um argumento. Ao fazer isso, apenas um argumento será passado para cada comando. Entretanto, o argumento será criado de uma linha inteira de entrada, não de apenas um único token. Também é possível usar a opção -L de xargs para que trate as linhas como argumentos, em vez do padrão de tokens delimitados por espaço em branco individuais. Usar a opção -I implica -L 1. A Listagem 15 mostra exemplos de uso tanto de -I quanto de -L

Listagem 15. Utilizando xargs com linhas de entrada
[ian@echidna lpi103-4]$ xargs -I XYZ echo "START XYZ REPEAT XYZ END" <text1
START 1 apple REPEAT 1 apple END
START 2 pear REPEAT 2 pear END
START 3 banana REPEAT 3 banana END
[ian@echidna lpi103-4]$ xargs -IX echo "<X><X>" <text2
<9      plum><9 plum>
<3      banana><3       banana>

<10     apple><10       apple>
[ian@echidna lpi103-4]$ cat text1 text2 | xargs -L2
1 apple 2 pear
3 banana 9 plum
3 banana 10 apple

Embora nossos exemplos tenham utilizado arquivos de texto simples para ilustração, você frequentemente desejará usar xargs com entradas como estas. Normalmente você estará lidando com uma grande lista de arquivo gerado de um comando como ls, find ou grep. A Listagem 16 mostra uma maneira como você pode passar uma listagem de diretório através de xargs para um comando como grep.

Listagem 16. Utilizando xargs com listas de arquivos
[ian@echidna lpi103-4]$ ls |xargs grep "1"
text1:1 apple
text2:10        apple
xaa:1 apple
yaa:1

O que acontece no último exemplo se um ou mais dos nomes de arquivo contiver um espaço? Se você usou o comando como na Listagem 16, então terá um erro. No mundo real, sua lista de arquivos pode vir de alguma fonte como um script ou um comando customizados, em vez de ls, ou você pode desejar passá-lo através de alguns outros estágios de pipeline para filtrá-lo melhor, então ignoraremos o fato de que você poderia simplesmente usar grep "1" * em vez dessa construção.

Para o comando ls, poderia ser utilizada a opção --quoting-style para obrigar os nomes de arquivo com problema a serem colocados entre aspas ou escapados. Uma solução melhor, quando disponível, é a opção -0 de xargs, então o caractere nulo (\0) é utilizado para delimitar argumentos de entrada. Embora ls não tenha uma opção para fornecer nomes de arquivo terminados em nulo como saída, muitos comandos possuem.

Na Listagem 17, primeiro copiamos text1 para "text 1" e então mostramos algumas maneiras de usar uma lista de nomes de arquivo contendo espaços em branco com xargs. Esses são para ilustração dos conceitos, uma vez que xargs podem ser difíceis de dominar. Em particular, o exemplo final de converter novos caracteres de linha em nulos não funcionaria se alguns nomes de arquivo já contivessem novos caracteres de linha. Na próxima parte deste artigo, veremos uma solução mais consistente utilizando o comando find para gerar uma saída adequada delimitada por nulo.

Listagem 17. Utilizando xargs com espaços em branco em nomes de arquivo
[ian@echidna lpi103-4]$ cp text1 "text 1"
[ian@echidna lpi103-4]$ ls *1 |xargs grep "1" # error
text1:1 apple
grep: text: No such file or directory
grep: 1: No such file or directory
[ian@echidna lpi103-4]$ ls --quoting-style escape *1
text1  text\ 1
[ian@echidna lpi103-4]$ ls --quoting-style shell *1
text1  'text 1'
[ian@echidna lpi103-4]$ ls --quoting-style shell *1 |xargs grep "1"
text1:1 apple
text 1:1 apple
[ian@echidna lpi103-4]$ # Illustrate -0 option of xargs

[ian@echidna lpi103-4]$ ls *1 | tr '\n' '\0' |xargs -0 grep "1"
text1:1 apple
text 1:1 apple

O comando xargs não criará comandos longos arbitrariamente. Até o Linux kernel 2.26.3, o tamanho máximo de um comando era limitado. Um comando como rm somepath/*, para um diretório contendo muitos arquivos com nomes longos, poderia falhar com uma mensagem indicando que o argumento era longo demais. Em sistemas Linux mais antigos, ou em sistemas UNIX que podem ainda ter a limitação, é útil saber como usar xargs de modo que você possa lidar com essas situações.

É possível usar a opção --show-limits para exibir os limites padrão de xargs, e a opção -s para limitar o tamanho dos comandos de saída a um número de caracteres máximo específico. Consulte as páginas principais para outras opções que não foram discutidas aqui.

Utilizando o comando find com a opção -exec ou com xargs

No artigo "Learn Linux 101: File and directory management," você aprenderá a usar o comando find para encontrar arquivos por nome, hora de modificação, tamanho ou outras características. Uma vez que você encontrar esse conjunto de arquivos, você frequentemente desejará fazer algo com eles: removê-los, copiá-los para outro local, renomeá-los ou alguma outra operação. Agora veremos a opção -exec de find, que possui funcionalidade similar a usar find e canalizar a saída para xargs.

Listagem 18. Utilizando find e -exec
[ian@echidna lpi103-4]$ find text[12] -exec cat text3 {} \;
This is a sentence.  This is a sentence.  This is a sentence.
1 apple
2 pear
3 banana
This is a sentence.  This is a sentence.  This is a sentence.
9       plum
3       banana
10      apple

Comparado ao que você já aprendeu sobre usar xargs, há diversas diferenças.

  1. Você precisa incluir {} para marcar onde o nome de arquivo vai constar no comando. Não é adicionado automaticamente no final.
  2. É necessário terminar o comando com um ponto e vírgula e deve ser escapado; \;, ';', ou ";" servirão.
  3. O comando é executado uma vez para cada arquivo de entrada.

Tente executar find text[12] |xargs cat text3 para você ver as diferenças.

Agora vamos retornar ao caso do espaço em branco no nome de arquivo. Na Listagem 19, tentamos usar find com -exec em vez de ls com xargs.

Listagem 19. Utilizando find e -exec com espaços em branco em nomes de arquivo
[ian@echidna lpi103-4]$ find . -name "*1" -exec grep "1" {} \;
1 apple
1 apple

Até aqui tudo bem. Mas não está faltando algo? Que arquivos continham as linhas encontradas por grep? O nome de arquivo está faltando porque find solicitou grep uma vez para cada arquivo, e grep é inteligente o bastante para saber que você apenas forneceu um nome de arquivo, então não é necessário dizer que arquivo foi.

Poderíamos usar xargs no lugar, mas já vimos problemas com espaços em branco em nomes de arquivo. Também aludimos ao fato de que find poderia produzir uma lista de nomes de arquivo com delimitadores nulos, e é isso que a opção -print0 faz. Versões modernas de encontrar podem ser delimitadas com um sinal de "+", em vez de ponto e vírgula, e isso faz o find passar por tantos nomes quanto forem possíveis em uma execução de um comando, similar à maneira como xargs funciona. Não é necessário dizer, é possível usar {} uma vez neste caso, e deve ser o último parâmetro do comando. A Listagem 20 mostra ambos os métodos.

Listing 20. Utilizando find e xargs com espaços em branco em nomes de arquivo
[ian@echidna lpi103-4]$ find . -name "*1" -print0 |xargs -0 grep "1"
./text 1:1 apple
./text1:1 apple
[ian@echidna lpi103-4]$ find . -name "*1" -exec grep "1" {} +
./text 1:1 apple
./text1:1 apple

Em geral, qualquer um dos métodos funcionará, e a escolha frequentemente é uma questão de estilo pessoal. Lembre-se que canalizar coisas com espaços desprotegidos ou em branco podem causar problemas, então use a opção -print0 com find se estiver canalizando a saída para xargs, e use a opção -0 para fazer com que xargs espere entrada delimitada por nulo. Outros comandos, incluindo tar, também suportam entrada delimitada por nulo utilizando a opção -0, então deve-se usá-la sempre para comandos que a suportem, a menos que tenha certeza de que sua lista de entrada não será um problema.

Um comentário final sobre operação em uma lista de arquivos. É sempre uma boa ideia testar cuidadosamente sua lista e também seus comandos com muita atenção antes de realizar uma operação em grande escala como remover ou renomear arquivos. Ter um bom backup também pode ser valioso.


Dividindo saída

Esta seção encerra com uma breve discussão de mais um comando. Às vezes você pode desejar ver a saída na sua tela enquanto salva uma cópia para mais tarde. Embora você poderia fazer isso redirecionando a saída de comando para um arquivo em uma janela e então utilizando tail -fn1 para acompanhar a saída em outra tela, usar o comando tee é mais fácil.

Usa-se tee com um pipeline. Os argumentos são um arquivo (ou múltiplos arquivos) para uma saída padrão. A opção -a anexa-se, em vez de substituir arquivos. Como vimos anteriormente em nossa discussão de pipelines, é necessário redirecionar stderr para stdout antes de canalizar para tee se você deseja salvar ambos. A Listagem 21 mostra tee sendo utilizado para salvar a saída em dois arquivos, f1 e f2.

Listagem 21. Dividindo stdout com tee
[ian@echidna lpi103-4]$ ls text[1-3]|tee f1 f2
text1
text2
text3
[ian@echidna lpi103-4]$ cat f1
text1
text2
text3
[ian@echidna lpi103-4]$ cat f2
text1
text2
text3

Recursos

Aprender

Obter produtos e tecnologias

  • Com o IBM trial software, disponível para download diretamente do developerWorks, construa seu próximo projeto de desenvolvimento em Linux.

Discutir

Comentários

developerWorks: Conecte-se

Los campos obligatorios están marcados con un asterisco (*).


Precisa de um ID IBM?
Esqueceu seu ID IBM?


Esqueceu sua senha?
Alterar sua senha

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

 


A primeira vez que você entrar no developerWorks, um perfil é criado para você. Informações no seu perfil (seu nome, país / região, e nome da empresa) é apresentado ao público e vai acompanhar qualquer conteúdo que você postar, a menos que você opte por esconder o nome da empresa. Você pode atualizar sua conta IBM a qualquer momento.

Todas as informações enviadas são seguras.

Elija su nombre para mostrar



Ao se conectar ao developerWorks pela primeira vez, é criado um perfil para você e é necessário selecionar um nome de exibição. O nome de exibição acompanhará o conteúdo que você postar no developerWorks.

Escolha um nome de exibição de 3 - 31 caracteres. Seu nome de exibição deve ser exclusivo na comunidade do developerWorks e não deve ser o seu endereço de email por motivo de privacidade.

Los campos obligatorios están marcados con un asterisco (*).

(Escolha um nome de exibição de 3 - 31 caracteres.)

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

 


Todas as informações enviadas são seguras.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=80
Zone=Linux
ArticleID=446239
ArticleTitle=Aprenda Linux, 101: Fluxos, canais e redirecionadores
publish-date=11112009