terça-feira, 5 de janeiro de 2010

Shell script: *, [], {}, ????, como utilizá-los?

Introdução

Outro recurso importantíssimo e que facilita muito a vida do administrador é a utilização de wildcards, seja ela para fins de buscas, cópias de aquivos para cá ou para lá, mover arquivos etc. Seja qual for o fim, os wildcards estão ao nosso lado para facilitar as tarefas.
Aqui será apresentando seu uso básico, em conjunto com comandos básicos, sendo eles: ls, cp, mv e rm.
Os wildcards, podem ser usados em inúmeros outros comandos como sed, find e para criação de expressões regulares, porém isso requer um conhecimento um pouco mais avançado e por isso não será abordado neste artigo.
De qualquer maneira entender seu uso básico irá lhe ajudar e muito. :)
Conteúdo programado:
  • Apresentação aos wildcards;
  • Entendendo seu uso na prática;
  • Considerações finais.
Uma ótima leitura a todos.
 
 

*, [], {}, ????

Os wildcards, chamados de coringas ou meta-caracteres, nos auxiliaram em diversas tarefas, então vamos conhecê-los.

 

Interrogação (?)

Este wildcard tem a finalidade de substituir um ou mais caracteres, porém os mesmos devem existir, senão a busca retornará um valor nulo. Vamos a um exemplo para melhor entendimento.
O exemplo que melhor se encaixa é, eu estou lá em /etc e quero saber os runlevels de meu sistema, simplesmente venho e digito:
# ls -d /etc/rc?.d
Outro exemplo, se eu quisesse listar tudo começado com rc e que tivesse mais três caracteres depois:
# ls -d /etc/rc???
Em minha opinião este é o wildcard menos utilizado, porém se bem implementado em uma busca tem suas vantagens.

 

Asterisco (*)

Este sim você usa em seu dia-a-dia e às vezes nem se dá conta, sem dúvidas o mais utilizado. O asterisco (*) substitui qualquer quantidade de caracteres e pode ser colocado no começo de uma busca, no meio ou no fim, ou ainda podemos deixar em evidencia apenas a extensão de um arquivo e poder listar tudo que tiver esta extensão em seu nome.
Vamos a um exemplo:
# ls /etc/*.conf
Ou mesmo:
# ls -d /etc/d*.conf

 

Colchetes []

Este também é muito interessante, ele nos permite adicionar condições especiais para a saída da busca, algo como qualquer texto que termine com um número de 1 a 9 ou todos os diretórios iniciados com letra maiúscula ou minúscula.
Porém no uso do colchetes, tem que haver uma lógica. Vamos a um exemplo.
Quero listar todos os arquivos iniciados de a até c no diretório /etc:
# ls /etc/[a-c]*
Porém não serão listados arquivos que iniciam com letra maiúscula, se eu quisesse listar as maiúsculas ficaria da seguinte maneira:
# ls /etc/[a-cA-C]*
E se eu quisesse listar todos os arquivos exceto os iniciados por vogais, ficaria assim:
# ls /etc/[^AEIOU]*
Estes são exemplos não convencionais, vocês entenderão bem daqui a pouco quando passarmos para a prática.
Fique atento a um coisa, veja que cada colchete substitui apenas um caractere.

 

Chaves {}

Este wildcard nos permite especificar uma combinação de caracteres, números ou trechos para serem combinados com o que estiver fora dele, assim fica meio confuso né, mas vamos a um exemplo que rapidamente vocês entenderam.
Digamos que eu esteja no diretório corrente e queira listar todos arquivos que iniciem com a palavra text:
# ls -la . {text}*
O que mais chama a atenção neste wildcard é que o mesmo pode ser combinado com comandos de criação de arquivos e diretório, o que não podemos fazer usando o wildcard [], isso facilita e muito quando se tem um padrão no nome do arquivo e só mude algum caractere, muito bom para ministrar aulas ou dar de exemplos em artigos. :)
Veja: eu quero criar dez arquivos iniciados com o nome aula. Vejo e emito o seguinte comando:
# touch aula{1,2,3,4,5,6,7,8,9,10}
Interessante né, agora que já entenderam o que cada wildcard faz, que tal aprofundar-se um pouco mais?

 

 

Utilizando os wildcards - modo listagem

Como em um artigo anterior, tentarei realizar uma interação com o leitor afim de tornar mais fácil o entendimento e aprendizado do assunto. Então vamos meter a mão na massa e abusar de seu uso. Tudo com a maior segurança. :)
Tudo ocorrerá na maioria das vezes no diretório /tmp, pois tudo é apagado assim que se rebota o sistema.
Nesta primeira parte, tratarei apenas da listagem, ou seja, explorar o que se tem em um diretório, e na segunda parte teremos um interação com os comandos cp e mv.
Vamos lá, navegue até o /tmp:

# cd /tmp

Dentro deste diretório criaremos quinze arquivos iniciados com "teste" e contendo números em seu final, vamos lá?
Criei os arquivos, pode seguir este exemplo em uma primeira vez apenas para entender seu uso, depois pode criar seus próprios testes, isso ajuda e muito no entendimento:

# touch teste{1,2,3,4,5,6,7,8,9,10,20,25,30,40,45}

Agora crie um arquivo chamado "otesteo":

# touch otesteo

Arquivos criados!
Vamos ver como ficou o cenário, e para já começar, listaremos apenas os arquivos que nos interessam, que consequentemente são os que acabamos de criar, para isso usaremos o (*):

# ls *test*
otesteo  teste10  teste20  teste3   teste4   teste45  teste6  teste8
teste1   teste2   teste25  teste30  teste40  teste5   teste7  teste9

Bom, mas qual é a finalidade destes arquivos?
Para que possamos entender o uso dos wildcards, precisaremos realizar testes, ou seja, entender como é feito, então trabalharemos em cima destes arquivos, movimentando-os para lá e para cá, removendo, realizando cópias, listagens, enfim, praticando.
Sem muitas delongas, vamos à pratica!
Primeiro listaremos os arquivos que contenham apenas um número no final de seu nome, usaremos o []:

# ls teste[1-9]
teste1  teste2  teste3  teste4  teste5  teste6  teste7  teste8  teste9

Perfeito, tente agora listar arquivos com dois números no final de seu nome, veja, para que consiga realizar tal listagem precisaremos repetir o uso dos [] na expressão. Mas porque? Para cada casa usamos um par de colchetes [], e assim sucessivamente. Se quisermos listar, por exemplo, arquivos que contenham o ano de criação, precisaremos usar 4 pares de colchetes, um para cada casa, vamos lá então:

# ls teste[1-9][0]
teste10  teste20  teste30  teste40

Percebem a diferença entre os dois?

# ls teste[1-9][0-5]
teste10  teste20  teste25  teste30  teste40  teste45

Já que com arquivos sem extensão já estamos nos saindo bem, que tal esquentarmos um pouco as coisas?
Bom, até aqui já conseguimos fazer listagens básicas certo? Mas e se fossem por suas extensões, se elas tivessem alguns outros caracteres, enfim, vamos ver estes cenários:
Lá em /tmp, onde tínhamos os arquivos:

otesteo  teste10  teste20  teste3   teste4   teste45  teste6  teste8
teste1   teste2   teste25  teste30  teste40  teste5   teste7  teste9

Algo bem básico, vamos criar arquivos chamados teste.txt teste.conf e 123teste.txt 123teste.conf.

# touch 123teste{.txt,.conf} teste{.txt,.conf}

Opa, aqui já outra coisa que podemos reparar, podemos criar arquivos de várias extensões diferentes sem precisar repetir o comando, então já podemos perceber também que poderemos listá-los sem problema, vamos lá.
Dentre todos aqueles nosso arquivos em /tmp, eu quero listar os seguintes: otesteo, 123teste.txt, 123teste.conf, teste.txt e teste.conf. Vamos ver como fica?

# ls *teste{o,.txt,.conf}
123teste.conf  123teste.txt  otesteo  teste.conf  teste.txt

Opa, perfeito, mas talvez alguém possa estar perdido neste ponto {o,.txt,.conf}. Certo, vejam em nossa busca, tínhamos uma única certeza inicial, todos os arquivos continham teste, então este é o nosso ponto de partida.
Analisando percebi que os arquivos de que necessitava continham números antes do teste e outros arquivos algumas extensões, assim ficaria mais simples, porém um de nossos arquivos continha uma letra antes e depois.
Então o *teste eliminou qualquer caractere antes deste, porém se tivéssemos usado *teste*{.txt,.conf}, não conseguiríamos suprir nossa busca, pois o * colocaria em nosso resultado qualquer caractere, então acabaríamos com um monte de arquivos.
O que fizemos para eliminar o problema, colocamos o {o,.txt,.conf} que só poderia me retornar qualquer arquivo que contivesse teste no meio e terminasse com uma letra o, como foi o nosso caso.
Claro este foi um exemplo simples, mas entender isso será fundamental, digo isso pois agora iniciaremos uma parte onde o cuidado e a certeza são as chaves para uma boa busca. xD
Espero que tenham entendido o que aqui quis passar, agora apresentarei a vocês a interação dos wildcards com outros comandos, vamos lá?

 

Utilizando os Wildcards - realizando movimentações

Anteriormente aprendemos a utilizar os wildcards, e mesmo em modo listagem, conseguimos entender como é sua sintaxe, ou seja, entendendo sua sintaxe, sabemos como utilizá-lo, independente do comando usado.
Esta decidi ser uma parte do artigo mais prática, ou seja, hands-on, colocaremos em prática tudo que foi visto, porém um pouco mais afundo. ;D
Como sempre trabalharemos dentro do diretório /tmp, porém realizaremos consulta fora do mesmo, ou seja, não saberemos o que realmente contém em outros diretórios a não ser o que nos interessa, então teremos que ser bem mais cautelosos na montagem de nossa expressão.
Antes de continuar, quero destacar aqui um pouco do que realizaremos, para um exemplo mais real, de cotidiano de um administrador, resolvi que realizaremos cópias de arquivos em diretórios como /etc, e como são cópias, não há risco de prejudicar o funcionamento do seu sistema.
Se você não se sentir a vontade, peço que não continue, mas se mesmo assim gostaria de ler, crie uma máquina virtual e ali realize seus testes.
Um exemplo agora, copiaremos todos os arquivos iniciados com a, b, c, e, f com extensão .conf de /etc para /tmp.
Antes sempre de montar sua expressão, raciocine em quais wildcards você deve usar, aqui temos uma sequência de letras, então poderíamos usar o [] e fazer algo como [a-f] não é?
Veja, a-b-c-d-e-f, não queremos d em nossa pesquisa, então não poderíamos usá-lo, pois acabaríamos tendo arquivos que não nos interessa. Fique sempre atento a isso, use o [] em uma sequência sem intervalos!
Nossa expressão ficaria mais ou menos assim:

# cp -v /etc/{a,b,c,e,f}*.conf /tmp
`/etc/adduser.conf' -> `/tmp/adduser.conf'
`/etc/brltty.conf' -> `/tmp/brltty.conf'
`/etc/casper.conf' -> `/tmp/casper.conf'
cp: cannot stat `/etc/e*.conf': No such file or directory
`/etc/fdmount.conf' -> `/tmp/fdmount.conf'
`/etc/fuse.conf' -> `/tmp/fuse.conf'

(perfeito, somente o que queria)
Ok, mas isso é pouco para nós, vamos a mais exemplos.
Agora copiaremos todos os arquivos que terminam com as letras r, s, t, u, z do diretório /etc e que tenham ainda extensão .conf para /tmp.
Vamos lá!

# cp -v /etc/*{r,s,t,u,z}.conf /tmp
`/etc/adduser.conf' -> `/tmp/adduser.conf'
`/etc/casper.conf' -> `/tmp/casper.conf'
`/etc/deluser.conf' -> `/tmp/deluser.conf'
`/etc/discover.conf' -> `/tmp/discover.conf'
`/etc/scrollkeeper.conf' -> `/tmp/scrollkeeper.conf'
`/etc/mke2fs.conf' -> `/tmp/mke2fs.conf'
`/etc/fdmount.conf' -> `/tmp/fdmount.conf'
`/etc/host.conf' -> `/tmp/host.conf'
`/etc/popularity-contest.conf' -> `/tmp/popularity-contest.conf'
cp: cannot stat `/etc/*u.conf': No such file or directory
cp: cannot stat `/etc/*z.conf': No such file or directory

Ainda percebemos que não tem arquivos terminados com u ou z.
Agora moveremos alguns arquivos. Antes criei um usuário com o nome da sua distribuição, mas crie um /home para ele também, no meu caso criei o usuário Debian.
Vamos então mover todos arquivos que acabamos de copiar de /etc para /tmp para o home do usuário criado (exceto os que terminem com a letra t) e que tenham extensão .conf.

# mv -v /tmp/*{r,s,u,z}.conf /home/debian
`/tmp/adduser.conf' -> `/home/debian/adduser.conf'
removed `/tmp/adduser.conf'
`/tmp/casper.conf' -> `/home/debian/casper.conf'
removed `/tmp/casper.conf'
`/tmp/deluser.conf' -> `/home/debian/deluser.conf'
removed `/tmp/deluser.conf'
`/tmp/discover.conf' -> `/home/debian/discover.conf'
removed `/tmp/discover.conf'
`/tmp/scrollkeeper.conf' -> `/home/debian/scrollkeeper.conf'
removed `/tmp/scrollkeeper.conf'
`/tmp/mke2fs.conf' -> `/home/debian/mke2fs.conf'
removed `/tmp/mke2fs.conf'
mv: cannot stat `/tmp/*u.conf': No such file or directory
mv: cannot stat `/tmp/*z.conf': No such file or directory

Simples não é?
Bom, acho que poderia deixar mais exemplos, mas creio eu que vocês devem ter captado a mensagem.
Espero também que tenha sido de ajuda a vocês. ;D

Considerações finais

O uso de wildcars pode nos auxiliar em inúmeras tarefas, porém para usar em desktops pode parecer um pouco sem sentido, mas para administradores de sistemas isso ajuda e muito, otimiza tarefas, buscas, verificações, enfim, você procura e realmente acha o que deseja. :)
É isso aí, espero que tenha sido útil a vocês e de fácil entendimento.

0 comentários :

Enviar um comentário