shell script

Download Shell Script

If you can't read please download the document

Upload: rogerio-emilio-silva

Post on 07-Jul-2015

2.027 views

Category:

Documents


0 download

TRANSCRIPT

  • 1. LINUX USERPapo de BotequimCurso de Shell ScriptPapo de BotequimVoc no agenta mais aquele seuporque, em ingls, Shell significa con- cha, carapaa, isto , fica entre o u-amigo usurio de Linux enchendo osurio e o sistema operacional, de forma que tudo que interage comseu saco com aquela histria de que o o sistema operacional, tem que passar pelo seu crivo.sistema fantstico e o Shell umaferramenta maravilhosa? A partirO ambiente Shell Bom j que para chegar aodesta edio vai ficar mais fcil en-ncleo do Linux, no seu ker-nel que o que interessa atender o porqu deste entusiasmo...todo aplicativo, necessria a filtragem do Shell, vamos enten-POR JULIO CEZAR NEVES der como ele funciona de forma a tirar o mximo proveito das in-meras facilidades que ele nos oferece.Dilogo entreouvido em uma mesa O Linux, por definio, um sistemade um botequim, entre ummultiusurio no podemos nunca nosusurio de Linux e um empur-esquecer disto e para permitir o acessorador de mouse: O ambiente Linuxde determinados usurios e barrar a en- Quem o Bash?Para voc entender o que e como fun-trada de outros, existe um arquivo cha- o filho caula da famlia Shell.ciona o Shell, primeiro vou te mostrarmado /etc/passwd, que alm de fornecer P cara! Ests a fim de me deixar como funciona o ambiente em camadas dados para esta funo de leo-de-ch-maluco? Eu tinha uma dvida e vocdo Linux. D uma olhada no grficocara do Linux, tambm prov informa-me deixa com duas!mostrado na Figura 1. es para o incio de uma sesso (ou No, maluco voc j h muito tem-Neste grfico podemos ver que a ca-login, para os ntimos) daqueles quepo: desde que decidiu usar aquele sis-mada de hardware a mais profunda e passaram por esta primeira barreira. Otema operacional que voc precisa formada pelos componentes fsicos doltimo campo de seus registros informareiniciar dez vezes por dia e ainda por seu computador. Em torno dela, vem aao sistema qual o Shell que a pessoacima no tem domnio nenhum sobre camada do kernel que o cerne do vai receber ao iniciar sua sesso.o que esta acontecendo no seu com-Linux, seu ncleo, e quem pe o hard-Lembra que eu te falei de Shell, fa-putador. Mas deixa isso pr l, poisware para funcionar, fazendo seu geren- mlia, irmo? Pois , vamos comear avou te explicar o que Shell e os com- ciamento e controle. Os programas e entender isto: o Shell a conceituaoponentes de sua famlia e ao final da comandos que envolvem o kernel, delede concha envolvendo o sistema opera-nossa conversa voc dir: Meu Deus se utilizam para realizar as tarefas para cional propriamente dito, o nomedo Shell! Porque eu no optei peloque foram desenvolvidos. Fechando tudogenrico para tratar os filhos desta idiaLinux antes?.isso vem o Shell, que leva este nomeque, ao longo dos muitos anos de exis-Quadro 1: Uma rapidinha nos principais sabores de Shell Bourne Shell (sh): Desenvolvido por Stephen do sh e a elas agregou muitas outras. A com-C Shell (csh): Desenvolvido por Bill Joy, da Bourne do Bell Labs (da AT&T, onde tambm patibilidade total com o sh vem trazendoUniversidade de Berkley, o Shell mais uti- foi desenvolvido o Unix), foi durante muitosmuitos usurios e programadores de Shelllizado em ambientes BSD. Foi ele quem intro- anos o Shell padro do sistema operacionalpara este ambiente. duziu o histrico de comandos. A Unix. tambm chamado de Standard ShellBoune Again Shell (bash): Desenvolvido ini- estruturao de seus comandos bem simi- por ter sido durante vrios anos o nico, e cialmente por Brian Fox e Chet Ramey, este lar da linguagem C. Seu grande pecado foi at hoje o mais utilizado. Foi portado para o Shell do projeto GNU. O nmero de seusignorar a compatibilidade com o sh, partindo praticamente todos os ambientes Unix e dis- adeptos o que mais cresce em todo o por um caminho prprio. tribuies Linux. mundo, seja por que ele o Shell padro do Alm destes Shells existem outros, mas irei Korn Shell (ksh): Desenvolvido por DavidLinux, seja por sua grande diversidade de falar somente sobre os trs primeiros, tratan- Korn, tambm do Bell Labs, um supercon- comandos, que incorpora inclusive diversosdo-os genericamente por Shell e assinalando junto do sh, isto , possui todas as facilidadescomandos caractersticos do C Shell.as especificidades de cada um.82 Agosto 2004www.linuxmagazine.com.br

2. Papo de Botequim LINUX USERtncia do sistema operacional Unix,redirecionamento, que pode ser deforam aparecendo. Atualmente existemCom que Shell eu vou?entrada (stdin), de sada (stdout) ou dosQuando digo que o ltimo campo do arqui-diversos sabores de Shell (veja Quadro 1 erros (stderr), conforme vou explicar avo /etc/passwd informa ao sistema qual ona pgina anterior). seguir. Mas antes precisamos falar de...Shell que o usurio vai usar ao se logar, istodeve ser interpretado ao p-da-letra. Se esteComo funciona o Shell campo do seu registro contm o termo prog, Substituio de VariveisO Shell o primeiro programa que vocao acessar o sistema o usurio executar o Neste ponto, o Shell verifica se as even-ganha ao iniciar sua sesso (se quiser- programa prog. Ao trmino da execuo, a tuais variveis (parmetros comeadosmos assassinar a lngua portuguesasesso do usurio se encerra automatica- por $), encontradas no escopo domente. Imagine quanto se pode incremen-podemos tambm dizer ao se logar) no comando, esto definidas e as substituitar a segurana com este simples artifcio.Linux. ele quem vai resolver um montepor seus valores atuais.de coisas de forma a no onerar o kernelcom tarefas repetitivas, poupando-o paravolvidos (inclusive o prprio programa), Substituio de Meta-tratar assuntos mais nobres. Como cadae retorna um erro caso o usurio que Caracteresusurio possui o seu prprio Shell inter- chamou o programa no esteja autor-Se algum meta-caracter (ou coringa,pondo-se entre ele e o Linux, o Shell izado a executar esta tarefa.como *, ? ou []) for encontrado na linhaquem interpreta os comandos digitados ede comando, ele ser substitudo porexamina as suas sintaxes, passando-os$ ls linuxseus possveis valores.esmiuados para execuo.linux Supondo que o nico item no seu pa! Esse negcio de interpretar co- diretrio corrente cujo nome comea mando no tem nada a ver com inter-Neste exemplo o Shell identificou o ls co- com a letra n seja um diretrio chamado pretador no, n?mo um programa e o linux como um pa- nomegrandeprachuchu, se voc fizer: Tem sim: na verdade o Shell um in-rmetro passado para o programa ls. terpretador que traz consigo uma po- $ cd n* derosa linguagem com comandos de Atribuio alto nvel, que permite construo deSe o Shell encontra dois campos separa-como at aqui quem est manipulando a loops, de tomadas de deciso e de ar-dos por um sinal de igual (=) sem espa-linha de comando ainda o Shell e o mazenamento de valores em variveis, os em branco entre eles, ele identifica programa cd ainda no foi executado, o como vou te mostrar. esta seqncia como uma atribuio.Shell expande o n* para nomegrandepra- Vou explicar as principais tarefas que o chuchu (a nica possibilidade vlida) e Shell cumpre, na sua ordem de exe-$ valor=1000executa o comando cd com sucesso. cuo. Preste ateno, porque esta ordem fundamental para o entendi-Neste caso, por no haver espaos em Entrega da linha de comando mento do resto do nosso bate papo. branco (que um dos caracteres reserva- para o kerneldos), o Shell identificou uma atribuio e Completadas todas as tarefas anteriores,Anlise da linha de comando colocou 1000 na varivel valor.o Shell monta a linha de comando, jNeste exame o Shell identifica os carac- com todas as substituies feitas eteres especiais (reservados) que tm sig- Resoluo de chama o kernel para execut-la em umnificado para a interpretao da linha eRedirecionamentosnovo Shell (Shell filho), que ganha umlogo em seguida verifica se a linha pas-Aps identificar os componentes da li- nmero de processo (PID ou Processsada um comando ou uma atribuio nha que voc digitou, o Shell parte para IDentification) e fica inativo, tirandode valores, que so os tens que voua resoluo de redirecionamentos.uma soneca durante a execuo do pro-descrever a seguir.O Shell tem incorporado ao seu elenco grama. Uma vez encerrado este processode habilidades o que chamamos de (e o Shell filho), o Shell pai recebeComandonovamente o controle e exibe umQuando um comando digi-prompt, mostrando que est prontotado no prompt (ou linha de Shellpara executar outros comandos.comando) do Linux, ele divi-dido em partes, separadas porProgramas e Comandos Cuidado na Atribuioespaos em branco: a primeiraNcleo ou KernelJamais faa:parte o nome do programa,cuja existncia ser verificada;Hardware $ valor = 1000 bash: valor: not foundem seguida, nesta ordem, vm Neste caso, o Bash achou a palavra valor iso-as opes/parmetros, redire- lada por espaos e julgou que voc estivessecionamentos e variveis. mandando executar um programa chama-Quando o programa identifi- do valor, para o qual estaria passando doiscado existe, o Shell verifica as parmetros: = e 1000.permisses dos arquivos en-Figura 1: Ambiente em camadas de um sistema Linux www.linuxmagazine.com.brAgosto 2004 83 3. LINUX USERPapo de BotequimDecifrando a Pedra de Roseta$ echo * esperando pelo teclado (Entrada Padro)Para tirar aquela sensao que voc tem $ echo *e como tambm no citei a sada, o quequando v um script Shell, que mais eu teclar ir para a tela (Sada Padro),parece uma sopa de letrinhas ou um con- Viu a diferena?criando desta forma como eu haviajunto de hierglifos, vou lhe mostrar os Aspas (): exatamente iguais ao aps- proposto um programa gago. Experi-principais caracteres especiais para quetrofo, exceto que, se a cadeia entremente!voc saia por a como Champollion deci- aspas contiver um cifro ($), umafrando a Pedra de Roseta. crase (`), ou uma barra invertida (),Redirecionamentop da Sadaestes caracteres sero interpretadosPadroCaracteres para remoo dopelo Shell. Para especificarmos a sada de um pro-significado.No precisa se estressar, eu no te dei grama usamos o smbolo > ou o isso mesmo, quando no desejamosexemplos do uso das aspas por que >>, seguido do nome do arquivo pa-que o Shell interprete um caractere voc ainda no conhece o cifro ($) ra o qual se deseja mandar a sada.especfico, devemos escond-lo dele.nem a crase (`). Daqui para frente - Vamos transformar o programa ante-Isso pode ser feito de trs maneiras difer- veremos com muita constncia o usorior em um editor de textos:entes, cada uma com sua peculiaridade:destes caracteres especiais; o mais Apstrofo (): quando o Shell v umaimportante entender seu significado. $ cat > Arqcadeia de caracteres entre apstrofos,ele retira os apstrofos da cadeia e noCaracteres de O cat continua sem ter a entrada especi-interpreta seu contedo.redirecionamentoficada, portanto est aguardando que osA maioria dos comandos tem uma entra- dados sejam teclados, porm a sua sada $ ls linuxm* da, uma sada e pode gerar erros. Estaest sendo desviada para o arquivo Arq. linuxmagazineentrada chamada Entrada Padro ou Assim sendo, tudo que esta sendo tecla- $ ls linuxm* stdin e seu dispositivo padro o tecladodo esta indo para dentro de Arq, de for- bash: linuxm* no such file U do terminal. Analogamente, a sada do ma que fizemos o editor de textos mais or directory comando chamada Sada Padro ou curto e ruim do planeta.stdout e seu dispositivo padro a tela Se eu fizer novamente:No primeiro caso o Shell expandiu o do terminal. Para a tela tambm soasterisco e descobriu o arquivo linux-enviadas normalmente as mensagens de $ cat > Arqmagazine para listar. No segundo, oserro oriundas dos comandos, chamadaapstrofos inibiram a interpretao doneste caso de Sada de Erro Padro ou Os dados contidos em Arq sero perdi-Shell e veio a resposta que no existe ostderr. Veremos agora como alterar este dos, j que antes do redirecionamento oarquivo linuxm*.estado de coisas. Shell criar um Arq vazio. Para colocar Contrabarra ou Barra Invertida (): i- Vamos fazer um programa gago. Para mais informaes no final do arquivo eudntico aos apstrofos exceto que a isto digite (tecle Enter ao final de cada deveria ter feito:barra invertida inibe a interpretao linha comandos do usurio so ilus-somente do caractere que a segue. trados em negrito):$ cat >> ArqSuponha que voc, acidentalmente,tenha criado um arquivo chamado * $ cat Redirecionamento da Sada(asterisco) o que alguns sabores de E-e-eu sou gago. Vai encarar? de Erro PadroUnix permitem e deseja remov-lo. E-e-eu sou gago. Vai encarar? Assim como por padro o Shell recebe osSe voc fizesse:dados do teclado e envia a sada para aO cat um comando que lista o con- tela, os erros tambm vo para a tela se $ rm * tedo do arquivo especificado para avoc no especificar para onde eles de-Sada Padro (stdout). Caso a entrada vem ser enviados. Para redirecionar osVoc estaria na maior encrenca, pois ono seja definida, ele espera os dados da erros, use 2> SaidaDeErro. Note que en-rm removeria todos os arquivos do stdin (a entrada padro). Ora como eu tre o nmero 2 e o sinal de maior (>)diretrio corrente. A melhor forma de no especifiquei a entrada, ele a estno existe espao em branco.fazer o servio : Vamos supor que durante a execuo Redirecionamento Perigosode um script voc pode, ou no (depen- $ rm *Como j havia dito, o Shell resolve a linha e dendo do rumo tomado pela execuodepois manda o comando para a execuo. do programa), ter criado um arquivoDesta forma, o Shell no interpreta o Assim, se voc redirecionar a sada de um chamado /tmp/seraqueexiste$$. Comoasterisco, evitando a sua expanso. arquivo para ele prprio, primeiramente o no quer ficar com sujeira no discoFaa a seguinte experincia cientfica: Shell esvaziaeste arquivo e depois mandargido, ao final do script voc coloca ao comando para execuo! Desta forma, linha a seguir:para sua alegria, voc acabou de perder o $ cd /etccontedo de seu querido arquivo. $ echo *rm /tmp/seraqueexiste$$84 Agosto 2004 www.linuxmagazine.com.br 4. Papo de BotequimLINUX USER caprichamos, n? Ento ao invs de sair Dados ou Erros? redigindo o mail direto no prompt, de Etiquetas Erradas Preste ateno! No confunda >> com 2>. O forma a tornar impossvel a correo de Um erro comum no uso de labels (como o primeiro anexa dados ao final de um arqui-fimftp do exemplo anterior) causado pela uma frase anterior onde, sem querer, vo, e o segundo redireciona a Sada de Erro presena de espaos em branco antes ou voc escreveu um ns vai, voc edita Padro (stderr) para um arquivo que estaps o mesmo. Fique muito atento quanto a um arquivo com o contedo da mensa- sendo designado. Isto importante! isso, por que este tipo de erro costuma dar gem e aps umas quinze verificaes uma boa surra no programador, at que seja sem constatar nenhum erro, decide detectado. Lembre-se: um label que se prezeCaso o arquivo no existisse seria envi- envi-lo e para tal faz: tem que ter uma linha inteira s para ele.ado para a tela uma mensagem de erro.Para que isso no acontea faa:$ mail [email protected] < Uarquivocommailparaochefe nada a partir deste ponto at encontrar rm /tmp/seraqueexiste$$ 2> Uo label fimftp. Voc no entenderia /dev/null e o chefe receber uma mensagem com o droga nenhuma, j que so instrues contedo do arquivocommailparaochefe. especficas do ftp.Para que voc teste a Sada de Erro Pa- Outro tipo de redirecionamento muito Se fosse s isso seria simples, masdro direto no prompt do seu Shell, voulouco que o Shell permite o chamadopelo prprio exemplo d para ver quedar mais um exemplo. Faa: here document. Ele representado por existem duas variveis ($Usuario e arquivodeerroslabel que segue o sinal $3para limitar a pesquisa primeira que, da mesma forma que vamos desen-posio da sada do ls longo (parmetrovolver um monte de programas paraAgora vamos rodar esse programinha: organizar os seus CDs de msica, com Tabela 1pequenas adaptaes voc pode fazer o $ teste passando parametros para U mesmo para organizar os CDs de soft-testar Posio Valores possveis 1- ware que vm com a Linux Magazine e bash: teste: cannot execute 2r ou - outros que voc compra ou queima, e 3w ou -disponibilizar esse banco de softwareOps! Esqueci-me de tornar o script exe- 4x,s(suid) ou -para todos os que trabalham com voc cutvel. Vou fazer isso e testar nova- (o Linux multiusurio, e como tal deve mente o programa:88Setembro 2004 www.linuxmagazine.com.br 8. Papo de BotequimLINUX USER $ chmod 755 testeExecute o programa:incluso de CDs no meu banco chamado $ teste passando parametros para Umusicas. O programa muito simples testar$ teste passando parametros para testar (como tudo em Shell). Veja a Listagem 1. 1o. parm -> passandoO programa teste recebeu 4 U O script simples e funcional; limito- 2o. parm -> parametrosparametrosme a anexar ao fim do arquivo musicas o 3o. parm -> para1o. parm -> passandoparmetro recebido. Vamos cadastrar 3 2o. parm -> parametroslbuns para ver se funciona (para noRepare que a palavra testar, que seria o 3o. parm -> paraficar enchendo lingia, suponho quequarto parmetro, no foi listada. IssoPara listar todos de uma Uem cada CD s existem duas msicas):ocorreu porque o programa teste s lista tacada eu faco passando Uos trs primeiros parmetros recebidos.parametros para testar$ musinc album3^Artista5UVamos execut-lo de outra forma: ~Musica5:Artista6~Musica5Repare que antes das aspas usei uma$ musinc album1^Artista1U $ teste passando parametros Ubarra invertida, para escond-las da ~Musica1:Artista2~Musica2 para testarinterpretao do Shell (se no usasse as $ musinc album 2^Artista3U 1o. parm -> passando parametroscontrabarras as aspas no apareceriam).~Musica3:Artista4~Musica4 2o. parm -> para Como disse, os parmetros recebem 3o. parm -> testar nmeros de 1 a 9, mas isso no significa Listando o contedo do arquivo musicas:que no posso usar mais de noveAs aspas no deixaram o Shell ver o parmetros. Significa que s posso $ cat musicasespao em branco entre as duasenderear nove. Vamos testar isso: album3^Artista5~Musica5:Artista6Uprimeiras palavras, e elas foram consid- ~Musica6eradas como um nico parmetro. E$ cat teste album1^Artista1~Musica1:Artista2Ufalando em passagem de parmetros, #!/bin/bash ~Musica2uma dica: veja na Tabela 2 algumas var-# Programa para testar passagem U album2^Artista3~Musica3:Artista4Uiveis especiais. Vamos alterar o pro- de parametros (3a. Versao)~Musica4grama teste para usar as novas variveis:echo O programa $0 recebeu $# U parametrosPodia ter ficado melhor. Os lbuns esto $ cat teste echo 11o. parm -> $11 fora de ordem, dificultando a pesquisa. #!/bin/bash shift Vamos alterar nosso script e depois test- # Programa para testar passagem U echo 2o. parm -> $1 lo novamente. Veja a listagem 2. Sim- de parametros (2a. Versao)shift 2 plesmente inseri uma linha que classifica echo O programa $0 recebeu $# U echo 4o. parm -> $1 o arquivo musicas, redirecionando a parametrossada para ele mesmo (para isso serve a echo 1o. parm -> $1Execute o programa:opo -o), aps cada lbum ser anexado. echo 2o. parm -> $2 echo 3o. parm -> $3 $ teste passando parametros para U$ cat musicas echo Para listar todos de uma U testaralbum1^Artista1~Musica1:Artista2U tacada eu faco $* O programa teste recebeu 4 U~Musica2 parametros que so: albu2^Artista3~Musica3:Artista4U Listagem 1: Incluindo CDs 11o. parm -> passando1~Musica4 na CDTeca 2o. parm -> parametrosalbum3^Artista5~Musica5:Artista6U 4o. parm -> testar~Musica6 $ cat musinc #!/bin/bashDuas coisas muito interessantes aconte- Oba! Agora o programa est legal e # Cadastra CDs (versao 1)ceram neste script. Para mostrar que osquase funcional. Ficar muito melhor em #nomes dos parmetros variam de $1 a $9 uma nova verso, que desenvolveremos echo $1 >> musicas digitei echo $11 e o que aconteceu? Oaps aprender a adquirir os dados da telaShell interpretou como sendo $1 seguidoe formatar a entrada.do algarismo 1 e listou passando1;Listagem 2O comando shift, cuja sintaxe shift n, Tabela 2: Variveis especiaispodendo o n assumir qualquer valor $ cat musincVarivelSignificadonumrico, despreza os n primeiros #!/bin/bash $0Contm o nome do programaparmetros, tornando o parmetro de # Cadastra CDs (versao 2) $#Contm a quantidade deordem n+1. parmetros passados #Bem, agora que voc j sabe sobre$*Contm o conjunto de todos os echo $1 >> musicaspassagem de parmetros, vamos voltar parmetros (muito parecido com $@) sort -o musicas musicasnossa cdteca para fazer o script dewww.linuxmagazine.com.brSetembro 2004 89 9. LINUX USER Papo de BotequimFicar listando arquivos com ogrep UListagem 5 - musexccomando cat no est com nada, vamos [arq1, arq2, ..., arqn]fazer um programa chamado muslist $ cat musexcpara listar um lbum, cujo nome ser O grep entendeu que deveria procurar a #!/bin/bashpassado como parmetro. Veja o cdigocadeia de caracteres album nos arquivos# Exclui CDs (versao 1)na Listagem 3: 2 e musicas. Como o arquivo 2 no#Vamos execut-lo, procurando peloexiste, grep gerou o erro e, por encontrar grep -v $1 musicas > /tmp/mus$$album 2. Como j vimos antes, para pas-a palavra album em todos os registros de mv -f /tmp/mus$$ musicassar a string album 2 necessrio pro- musicas, listou a todos.teg-la da interpretao do Shell, para melhor ignorarmos maisculas eque ele no a interprete como dois minsculas na pesquisa. Resolveremosmando. Estamos ento prontos paraparmetros. Exemplo: os dois problemas com a Listagem 4. desenvolver o script para remover CDs Nesse caso, usamos a opo -i do grep empenados da sua CDteca. Veja o $ muslist album 2 que, como j vimos, serve para ignorarcdigo da Listagem 5. grep: cant open 2maisculas e minsculas, e colocamos o Na primeira linha mandei para musicas: album1^Artista1~Musica1U $1 entre aspas, para que o grep continu-/tmp/mus$$ o arquivo musicas, sem os :Artista2~Musica2 asse a ver a cadeia de caracteres resul-registros que atendessem a consulta feita musicas: album2^Artista3~Musica3U tante da expanso da linha pelo Shell pelo comando grep. Em seguida, movi :Artista4~Musica4 como um nico argumento de pesquisa./tmp/mus$$ por cima do antigo musicas. musicas:album3^Artista5~Musica5UUsei o arquivo /tmp/mus$$ como arqui- :Artista6~Musica6 $ muslist album 2 vo de trabalho porque, como j havia album2^Artista3~Musica3:Artista4U citado no artigo anterior, o $$ contm oQue lambana! Onde est o erro? Eu tive~Musica4PID (identificao do processo) e, dessao cuidado de colocar o parmetro pas-forma, cada um que editar o arquivosado entre aspas para o Shell no o Agora repare que o grep localiza a musicas o far em um arquivo de tra-dividir em dois! , mas repare como ocadeia pesquisada em qualquer lugar dobalho diferente, evitando colises.grep est sendo executado: registro; ento, da forma que estamosOs programas que fizemos at aqui fazendo, podemos pesquisar por lbum, ainda so muito simples, devido falta grep $1 musicas por msica, por intrprete e mais.de ferramentas que ainda temos. Mas Quando conhecermos os comandosbom praticar os exemplos dados porque,Mesmo colocando lbum 2 entre aspas, condicionais, montaremos uma nova eu prometo, chegaremos a desenvolverpara que fosse encarado como um nicoverso de muslist que permitir especi- um sistema bacana para controle dosparmetro, quando o $1 foi passado peloficar por qual campo pesquisar. seus CDs. Na prxima vez que nosShell para o comando grep, transformou- Ah! Em um dia de vero voc foi encontrarmos, vou te ensinar como fun-se em dois argumentos. Dessa forma, opraia, esqueceu os CDs no carro, aquele cionam os comandos condicionais econtedo da linha que o grep executousolzinho de 40 graus empenou seuaprimoraremos mais um pouco essesfoi o seguinte:disco favorito e agora voc precisa descripts. Por hoje chega! J falei demais e uma ferramenta para remov-lo doestou de goela seca! Garom! Mais um grep album 2 musicasbanco de dados? No tem problema, sem colarinho!s vamos desenvolver um script chamadoComo a sintaxe do grep :musexc, para excluir estes CDs. INFORMAESAntes de desenvolver o bacalho, Listagem 3 - muslistquero te apresentar a uma opo bas- [1] http://www.revistadolinux.com.br/ed/003/ tante til da famlia de comandos grep. ferramentas.php3 $ cat muslist a opo -v, que quando usada lista todos [2] http://www.revistadolinux.com.br/ed/007/ #!/bin/bash os registros da entrada, exceto o(s) local-ereg.php3 # Consulta CDs (versao 1) izado(s) pelo comando. Exemplos: [3] http://www.aurelio.net/er/livro/ # grep $1 musicas $ grep -v album 2 musicas album1^Artista1~Musica1:Artista2UJulio Cezar Neves SOBRE O AUTORAnalista de Suporte de Listagem 4~Musica2Sistemas desde 1969 emuslist melhoradoalbum3^Artista5~Musica5:Artista6Utrabalha com Unix ~Musica6 desde 1980, quando $ cat muslistfez parte da equipe #!/bin/bash Conforme expliquei antes, o grep doque desenvolveu o # Consulta CDs (versao 2)SOX, um sistema exemplo listou todos os registros de #operacional similar ao Unix, produzido musicas exceto o referente a album 2,pela Cobra Computadores. grep -i $1 musicas porque atendia ao argumento do co-90 Setembro 2004www.linuxmagazine.com.br 10. Papo de BotequimLINUX USER Curso de Shell Script Papo de botequim III Um chopinho, um aperitivo e o papo continua. Desta vez vamos aprender alguns comandos de manipulao de cadeias de caracteres, que sero muito teis na hora de incrementar nossa CDteca. POR JULIO CEZAR NEVESG aron! traga dois chopes porfavor que hoje eu vou ter quefalar muito. Primeiro queromostrar uns programinhas simplesde usar e muito teis, como o cut, queEnto, recapitulando, o layout do arquivo o seguinte: nome do lbum^intrprete1~nome da msica1:...: intrpreten~nome da msican, isto , o nome do lbum ser separado por umArtista2Artista4Artista6Artista8 usado para cortar um determinado circunexo (^) do resto do registro, que Para entender melhor isso, vamos anali-pedao de um arquivo. A sintaxe e formado por diversos grupos compos-sar a primeira linha de musicas:alguns exemplos de uso podem ser vis-tos pelo intrprete de cada msica dotos no Quadro 1: CD e a respectiva msica interpretada. $ head -1 musicas Como d para ver, existem quatroEstes grupos so separados entre si poralbum 1^Artista1~Musica1: Usintaxes distintas: na primeira (-c 1-5) dois-pontos (:) e o intrprete ser sepa-Artista2~Musica2especifiquei uma faixa, na segunda rado do nome da msica por um til (~).(-c -6) especifiquei todo o texto at Ento, para pegar os dados referentes Ento observe o que foi feito:uma posio, na terceira (-c 4-) tudo de a todas as segundas msicas do arquivouma determinada posio em diante emusicas, devemos digitar:album 1^Artista1~Musica1: Una quarta (-c 1,3,5,7,9), s as posiesArtista2~Musica2determinadas. A ltima possibilidade$ cut -f2 -d: musicas(-c -3,5,8-) foi s para mostrar que pode-Artista2~Musica2Desta forma, no primeiro cut o primeiromos misturar tudo.Artista4~Musica4campo do delimitador (-d) dois-pon- Mas no pense que acabou por a! Artista6~Musica5tos (:) album 1^Artista1~Musica1 e oComo voc deve ter percebido, estaArtista8~Musica8@10_L:segundo, que o que nos interessa, forma de cut muito til para lidar comArtista2~Musica2. Vamos ento ver oarquivos com campos de tamanho xo, Ou seja, cortamos o segundo campoque aconteceu no segundo cut:mas atualmente o que mais existe so z(-f de eld, campo em ingls) delimi-arquivos com campos de tamanho vari- tado (-d) por dois-pontos (:). Mas, se Artista2~Musica2vel, onde cada campo termina com um quisermos somente os intrpretes, deve-delimitador. Vamos dar uma olhada no mos digitar: Agora, primeiro campo do delimitadorarquivo musicas que comeamos a pre-(-d) til (~), que o que nos interessa,parar na ltima vez que viemos aqui no$ cut -f2 -d: musicas | cut U Artista2 e o segundo Musica2. Sebotequim. Veja o Quadro 2. -f1 -d~o raciocnio que fizemos para a pri- www.linuxmagazine.com.brOutubro 200485 11. LINUX USERPapo de Botequim Quadro 1 O comando cutmeira linha for aplicado ao restante do arquivo, chegaremos resposta ante- posta a um exerccio prtico, valendo nota, que passei ele me entregou um riormente dada. Outro comando muito script com todos os comandos sepa- A sintaxe do cut : cut -c PosIni-PosFim interessante o tr que serve para subs-rados por ponto-e-vrgula (lembre-se [arquivo], onde PosIni a posio inicial, e tituir, comprimir ou remover caracteres.que o ponto-e-vrgula serve para sepa- PosFim a posio nal. Veja os exemplos: Sua sintaxe segue o seguinte padro:rar diversos comandos em uma mesma linha). Vou dar um exemplo simpli- $ cat numerostr [opes] cadeia1 [cadeia2]cado, e idiota, de um script assim: 1234567890 0987654321 O comando copia o texto da entrada $ cat confuso 1234554321 padro (stdin), troca as ocorrncia dosecho leia Programao Shell U 9876556789 caracteres de cadeia1 pelo seu corres- Linux do Julio Cezar Neves U pondente na cadeia2 ou troca mltiplas > livro;cat livro;pwd;ls;rm U $ cut -c1-5 numeros ocorrncias dos caracteres de cadeia1 -f livro2>/dev/null;cd ~ 12345 por somente um caracter, ou ainda 09876 caracteres da cadeia1. As principaisEu executei o programa e ele funcionou: 12345 opes do comando so mostradas na 98765 Tabela 1.$ confuso Primeiro veja um exemplo bem bobo: leia Programao Shell Linux U $ cut -c-6 numerosdo Julio Cezar Neves 123456$ echo bobo | tr o a/home/jneves/LM 098765babaconfuso livro musexc musicas 123455musinc muslist numeros 987655 Isto , troquei todas as ocorrncias da letra o pela letra a. Suponha que emMas nota de prova coisa sria (e nota $ cut -c4- numeros determinado ponto do meu script eude dlar mais ainda) ento, para 4567890 pea ao operador para digitar s ou nentender o que o aluno havia feito, o 7654321 (sim ou no), e guardo sua resposta chamei e em sua frente digitei: 4554321 na varivel $Resp. Ora, o contedo de 6556789 $Resp pode conter letras maisculas$ tr ; n < confuso ou minsculas, e desta forma eu teriaecho leia Programao Shell U $ cut -c1,3,5,7,9 numeros que fazer diversos testes para saber seLinux do Julio Cezar Neves 13579 a resposta dada foi S, s, N ou n. Ento opwd 08642 melhor fazer:cd ~ 13542ls -l 97568$ Resp=$(echo $Resp | tr SN sn) rm -f lixo 2>/dev/null $ cut -c -3,5,8- numeros e aps este comando eu teria certezaO cara cou muito desapontado, porque 1235890 de que o contedo de $Resp seria um em dois ou trs segundos eu des z a 0986321 s ou um n. Se o meu arquivo ArqEntgozao que ele perdeu horas para fazer. 1235321 est todo em letras maisculas e desejo Mas preste ateno! Se eu estivesse em 9875789 pass-las para minsculas eu fao:uma mquina Unix, eu teria digitado:$ tr A-Z a-z < ArqEnt > / tmp/$$$ tr ; 012 < confuso Quadro 2 O arquivo $ mv -f /tmp/$$ ArqEntmusicasAgora veja a diferena entre o resultado Note que neste caso usei a notao A- de um comando date executado hoje e Z para no escrever ABCDYZ. Outrooutro executado h duas semanas: $ cat musicas tipo de notao que pode ser usada so album 1^Artista1~Musica1:U as escape sequences (como eu traduzi-Sun Sep 19 14:59:54 2004 Artista2~Musica2 ria? Seqncias de escape? Meio semSun Sep 5 10:12:332004 album 2^Artista3~Musica3:U sentido, n? Mas v l) que tambm Artista4~Musica4 so reconhecidas por outros comandosNotou o espao extra aps o Sep na album 3^Artista5~Musica5:U e tambm na linguagem C, e cujo signi-segunda linha? Para pegar a hora eu Artista6~Musica5 cado voc ver na Tabela 2:deveria digitar: album 4^Artista7~Musica7:UDeixa eu te contar um causo: um Artista8~Musica8 aluno que estava danado comigo resol-$ date | cut -f 4 -d veu complicar minha vida e como res- 14:59:5486Outubro 2004 www.linuxmagazine.com.br 12. Papo de Botequim LINUX USERMas h duas semanas ocorreria o Bem a opo -d do tr remove do arquivo E veja tambm o date:seguinte: todas as ocorrncias do caractere espe-cificado. Desta forma eu removi os $ date$ date | cut -f 4 -d caracteres indesejados, salvei o texto Mon Sep 20 10:47:19 BRT 20045 em um arquivo temporrio e posterior-mente renomeei-o para o nome original. Repare que o ms e o dia esto noIsto porque existem 2 caracteres em Uma observao: em um sistema Unix mesmo formato em ambos os coman-branco antes do 5 (dia). Ento o idealeu deveria digitar:dos. Ora, se em algum registro do whoseria transformar os espaos em branco eu no encontrar a data de hoje, sinalconsecutivos em somente um espao $ tr -d 015 < ArqDoDOS.Uque o usurio est logado h maispara poder tratar os dois resultados do txt > /tmp/$$de um dia, j que ele no pode ter secomando date da mesma forma, e isso logado amanh Ento vamos guar-se faz assim:Uma dica: o problema com os termina- dar o pedao que importa da data de dores de linha (CR/LF) s aconteceu hoje para depois procur-la na sada do$ date | tr -s porque a transferncia do arquivo foi comando who:Sun Sep 5 10:12:33 2004feita no modo binrio (ou image), Se antes da transmisso do arquivo tivesse$ Data=$(date | cut -f 2-3 UE agora eu posso cortar: sido estipulada a opo ascii do ftp, isto-d ) no teria ocorrido.$ date | tr -s | cut -f 4 U Olha, depois desta dica t comeando a Eu usei a construo $(...), para prio- -d gostar deste tal de shell, mas ainda temrizar a execuo dos comandos antes10:12:33 muita coisa que no consigo fazer.de atribuir a sua sada varivel Data. Pois , ainda no te falei quase nadaVamos ver se funcionou:Olha s como o Shell est quebrando o sobre programao em shell, aindagalho. Veja o contedo de um arquivotem muita coisa para aprender, mas$ echo $Databaixado de uma mquina Windows: com o que aprendeu, j d para resol- Sep 20ver muitos problemas, desde que voc $ cat -ve ArqDoDOS.txt adquira o modo shell de pensar. Voc Beleza! Agora, o que temos que fazer Este arquivo^M$seria capaz de fazer um script que digaprocurar no comando who os registros foi gerado pelo^M$ quais pessoas esto logadas h maisque no possuem esta data. DOS/Win e foi^M$ de um dia no seu servidor? baixado por um^M$ Claro que no! Para isso seria necess- Ah! Eu acho que estou entendendo! ftp mal feito.^M$rio eu conhecer os comandos condicio- Voc falou em procurar e me ocorreu onais que voc ainda no me explicou comando grep, estou certo?Dica: a opo -v do cat mostra os carac-como funcionam. - Deixa eu tentar Certssimo! S que eu tenho que usar oteres de controle invisveis, com a nota- mudar um pouco a sua lgica e traz-grep com aquela opo que ele s listao ^L, onde ^ a tecla Control e L la para o modo shell de pensar, mas os registros nos quais ele no encon-a respectiva letra. A opo -e mostra o antes melhor tomarmos um chope. trou a cadeia. Voc se lembra que nal da linha como um cifro ($). Agora que j molhei a palavra, vamos opo essa? Isto ocorre porque no DOS o m dos resolver o problema que te propus. Veja Claro, a -vregistros indicado por um Carriage como funciona o comando who: Isso! T cando bom! Vamos ver:Return (r Retorno de Carro, CR) eum Line Feed (f Avano de Linha, ou $ who $ who | grep -v $DataLF). No Linux porm o nal do regis-jneves pts/ U jnevespts/ Utro indicado somente pelo Line Feed. 1Sep 1813:401 Sep 18 13:40Vamos limpar este arquivo: rtorrespts/ U 0Sep 2007:01Se eu quisesse um pouco mais de perfu-$ tr -d r < ArqDoDOS.txt > /tmp/$$rlegaria pts/ U maria eu faria assim:$ mv -f /tmp/$$ ArqDoDOS.txt 1Sep 2008:19 lcarlospts/ U $who | grep -v $Data |UAgora vamos ver o que aconteceu: 3Sep 2010:01 cut -f1 -d jneves $ cat -ve ArqDoDOS.txtTabela 1 O comando tr Este arquivo$OpoSignicadoViu? No foi necessrio usar comando foi gerado pelo$condicional, at porque o nosso-s Comprime n ocorrncias de DOS/Rwin e foi$ cadeia1 em apenas uma comando condicional, o famoso if, no baixado por um$ testa condio, mas sim instrues.-d Remove os caracteres de cadeia1 ftp mal feito.$ Mas antes veja isso:www.linuxmagazine.com.br Outubro 200487 13. LINUX USERPapo de Botequim $ ls musicasTabela 2/dev/null musicas Seqncia Signicado Octalthen $ echo $? tTabulao011echo Usuario $1 j U 0 nNova linha 012 existe $ ls ArqInexistente else ls: ArqInexistente: No such U vTabulao013if useradd $1 le or directoryVertical then $ echo $? fNova 014 echo Usurio $1 U 1 Pginaincludo em /etc/passwd $ who | grep jneves rIncio da015else jnevespts/1 Sep 18 Ulinha echo Problemas no U Uma barra0134 13:40 (10.2.4.144)cadastramento. Voc root? invertida $ echo $? 0 $ who | grep julianaj existe $ echo $? else Vamos test-lo como um usurio normal : 1if useradd $1then $ incusu ZeNinguem O que que esse $? faz a? Algo come-echo Usurio $1 U./incusu[6]: useradd: not found ado por cifro ($) parece ser uma vari-includo em /etc/passwd Problemas no cadastramento. U vel, certo? Sim uma varivel queelse Voc root? contm o cdigo de retorno da ltimaecho Problemas no U instruo executada. Posso te garan-cadastramento. Voc root? Aquela mensagem de erro no deveria tir que se esta instruo foi bem suce- aparecer! Para evitar isso, devemos dida, $? ter o valor zero, caso contrrioredirecionar a sada de erro (stderr) do seu valor ser diferente de zero. O quecomando useradd para /dev/null. A ver- nosso comando condicional (if) faz Repare que o if est testando direto oso nal ca assim: testar esta varivel. Ento vamos ver acomando grep e esta a sua nalidade. sua sintaxe: Caso o if seja bem sucedido, ou seja, o$ cat incusuusurio (cujo nome est em $1) foi #!/bin/bash if cmd encontrado em /etc/passwd, os coman- # Verso 3 then dos do bloco do then sero executadosif grep ^$1 /etc/passwd > Ucmd1(neste exemplo, apenas o echo). Caso /dev/nullcmd2contrrio, as instrues do bloco do elsethencmdnsero executadas, quando um novo if echo Usuario $1 j U else testa se o comando useradd foi execu-existecmd3tado a contento, criando o registro do elsecmd4usurio em /etc/passwd, ou exibindo if useradd $1 2> /dev/nullcmdmuma mensagem de erro, caso contrrio. then Executar o programa e passe como echo Usurio $1 Uparmetro um usurio j cadastrado:includo em /etc/passwd Ou seja, caso comando cmd tenha sido else executado com sucesso, os comandos$ incusu jneves echo Problemas no U do bloco do then (cmd1, cmd2 e cmdn)jneves:x:54002:1001:Julio Neves: Ucadastramento. Voc root? sero executados, caso contrrio, os/home/jneves:/bin/ U comandos do bloco opcional do elsebash (cmd3, cmd4 e cmdm) sero executados. Usuario jneves ja existe O bloco do if terminando com um . Depois disso, vejamos o comportamento Vamos ver na prtica como isso fun-No exemplo dado, surgiu uma linha do programa, se executado pelo root: ciona, usando um script que inclui usu-indesejada, ela a sada do comando rios no arquivo /etc/passwd:grep. Para evitar que isso acontea, $ incusu botelhodevemos desviar a sada para /dev/null.Usurio botelho incluido em U $ cat incusu O programa ca assim:/etc/passwd #!/bin/bash # Verso 1$ cat incusu E novamente: if grep ^$1 /etc/passwd #!/bin/bash then# Verso 2$ incusu botelhoecho Usuario $1U if grep ^$1 /etc/passwd > U Usurio botelho j existe88 Outubro 2004 www.linuxmagazine.com.br 14. Papo de Botequim LINUX USERLembra que eu falei que ao longo dos no incio da cadeia e cifro ($) no m, Como voc viu, o programa melho-nossos papos e chopes os nossos pro- servem para testar se o parmetro (o rou um pouquinho, mas ainda no estgramas iriam se aprimorando? Ento lbum e seus dados) exatamente igual pronto. medida que eu te ensinar avejamos agora como podemos melhorara algum registro j existente. Vamos programar em shell, nossa CDteca vaio nosso programa para incluir msicasexecutar nosso programa novamente, car cada vez melhor.na "CDTeca": mas desta vez passamos como parme- Entendi tudo que voc me explicou, tro um lbum j cadastrado, pra ver o mas ainda no sei como fazer um if $ cat musincque acontece: para testar condies, ou seja o uso #!/bin/bash normal do comando. # Cadastra CDs (versao 3) $ musinc album 4^Artista7~ U Para isso existe o comando test, que # Musica7:Artista8~Musica8 testa condies. O comando if testa if grep ^$1$ musicas > UEste lbum j est cadastrado o comando test. Como j falei muito, /dev/null preciso de uns chopes para molhar a thenE agora um no cadastrado:palavra. Vamos parar por aqui e naecho Este lbum j est Uprxima vez te explico direitinho o cadastrado$ musinc album 5^Artista9~ U uso do test e de diversas outras sinta- elseMusica9:Artista10~Musica10 xes do if.echo $1 >> musicas $ cat musicas Falou! Acho bom mesmo porque eusort musicas -o musicasalbum 1^Artista1~Musica1: U tambm j t cando zonzo e assim Artista2~Musica2tenho tempo para praticar esse monte album 2^Artista3~Musica3: U de coisas que voc me falou hoje.Como voc viu, uma pequena evolu-Artista4~Musica4 Para xar o que voc aprendeu, tenteo em relao verso anterior. Antesalbum 3^Artista5~Musica5: Ufazer um scriptizinho para informar sede incluir um registro (que na versoArtista6~Musica5 um determinado usurio, cujo nomeanterior poderia ser duplicado), testa-album 4^Artista7~Musica7: User passado como parmetro, estmos se o registro comea (^) e termina Artista8~Musica8logado no sistema ou no.($) de forma idntica ao parmetro album 5^Artista9~Musica9: U A Chico! traz mais dois chopes pralbum passado ($1). O circunexo (^) Artista10~Musica10mim por favor www.linuxmagazine.com.br Outubro 2004 89 15. LINUX USERPapo de BotequimCurso de Shell ScriptPapo debotequim IVO garon j perdeu a conta das cervejas, e o assunto no acaba. Desta Dave Hamilton - www.sxc.huvez vamos aprender a testar os mais variados tipos de condies,para podermos controlar a execuo de nosso programa de acordocom a entrada fornecida pelo usurio. POR JULIO CEZAR NEVESE a cara, tentou fazer o exerccioque te pedi em nosso ltimoencontro? Claro que sim! Em programao, se voc no treinar no aprende. Voc $ logado jneves jneves pts/0 12:02 (10.2.4.144) jneves est logado Oct 18 U Ah, agora sim! Lembre-se dessa pega- dinha: a maior parte dos comandos tem uma sada padro e uma sada de erros (o grep uma das poucas excees: ele no exibe uma mensagem de erro me pediu um script para informar seRealmente funcionou. Passei meuquando no acha uma cadeia de carac- um determinado usurio, cujo nomenome de usurio como parmetro e teres) e devemos redirecion-las para o ser passado como parmetro para o ele disse que eu estava logado, pormburaco negro quando necessrio. script, est logado (arghh!) ou no. ele imprimiu uma linha extra, que eu Bem, agora vamos mudar de assunto: Fiz o seguinte:no pedi, que a sada do comando na ltima vez que nos encontramoswho. Para evitar que isso acontea, aqui no botequim, quando j estvamos $ cat logado s mand-la para o buraco negro do de goela seca, voc me perguntou comomundo UNIX, o /dev/null. Vejamos se testam condies. Para isso, usamos #!/bin/bashento como caria: o comando test # Pesquisa se um usurio est # logado ou no $ cat logadoTestes #!/bin/bash Todos estamos acostumados a usar o if who | grep $1# Pesquisa se uma pessoa est if para testar condies, e estas so then# logada ou no (verso 2)sempre maior que, menor que, maiorecho $1 est logadoif who | grep $1 > /dev/nullou igual a, menor ou igual a, igual a e elsethenecho $1 no est no pedaoecho $1 est logado Tabela 1 Opes do elsetest para arquivosecho $1 no est no pedao OpoVerdadeiro se Calma rapaz! J vi que voc chegou -e arq arq existe cheio de teso. Primeiro vamos pedir-s arq arq existe e tem tamanho maior que zero os nossos chopes de praxe e depoisAgora vamos aos testes: vamos ao Shell. Chico, traz dois cho- -f arq arq existe e um arquivo regular pes, um sem colarinho!$ logado jneves -d arq arq existe e um diretrio -r arq arq existe e com direito de leitura Aaah! Agora que j molhamos os nos- jneves est logado -w arq arq existe e com direito de escrita sos bicos, vamos dar uma olhada nos $ logado chico -x arq arq existe e com direito de execuo resultados do seu programa: chico no est no pedao84 edio 04 www.linuxmagazine.com.br 16. Papo de Botequim LINUX USER Tabela 2 Opes do testNo exemplo, testei a existncia docadeia de caracteres 01 realmente para cadeias de caracteres diretrio lmb. Se no existisse (else), ele diferente de 1. Porm, a coisa mudaseria criado. J sei, voc vai criticar a de gura quando as variveis so testa-Opo Verdadeiro se:minha lgica dizendo que o script no das numericamente, j que o nmero 1-z cadeia Tamanho de cadeia zeroest otimizado. Eu sei, mas queria que igual ao nmero 01.-n cadeia Tamanho de cadeia maior que zerocadeiaA cadeia cadeia tem tamanho maior que zerovoc o entendesse assim, para entoPara mostrar o uso dos conectores -oc1 = c2 Cadeia c1 e c2 so idnticaspoder usar o ponto-de-espantao (!)(ou) e -a (e), veja um exemplo animal,como um negador do test. Veja s: programado direto no prompt do Bash.Me desculpem os zologos, mas eudiferente de. Para testar condies em if test ! -d lmb no entendo nada de reino, lo, classe,Shell Script usamos o comando test, s then ordem, famlia, gnero, espcie e outrasque ele muito mais poderoso do quemkdir lmb coisas do tipo, desta forma o que estouaquilo com que estamos acostuma- chamando de famlia ou de gnero temdos. Primeiramente, veja na Tabela 1 cd lmb grande chance de estar total e comple-as principais opes (existem muitastamente incorreto:outras) para testar arquivos em disco Desta forma o diretrio lmb seriae na Tabela 2 as principais opes paracriado somente se ele ainda no exis- $ Familia=felinaeteste de cadeias de caracteres.tisse, e esta negativa deve-se ao ponto $ Genero=gato de exclamao (!) precedendo a opo$ if test $Familia = canidea UTabela 3 Opes do-d. Ao m da execuo desse fragmento-a $Genero = lobo -o $Familia = U test para nmeros de script, com certeza o programa esta- felina -a $Genero = leo ria dentro do diretrio lmb. Vamos ver> thenOpo Verdadeiro seSignicado dois exemplos para entender a diferena >echo Cuidadon1 -eq n2 n1 e n2 so iguais equal na comparao entre nmeros e entre > elsen1 -ne n2 n1 e n2 no so iguais not equal cadeias de caracteres.>echo Pode passar a mon1 -gt n2 n1 maior que n2greater thann1 -ge n2 n1 maior ou igual a n2 greater or equal> n1 -lt n2 n1 menor que n2less than cad1=1Pode passar a mon1 -le n2 n1 menor ou igual a n2 less or equal cad2=01 if test $cad1 = $cad2Neste exemplo, caso o animal fosse then da famlia candea e (-a) do gnero lobo,Pensa que acabou? Engano seu! Agoraecho As variveis so iguais.ou (-o) da familia felina e (-a) do gnero hora de algo mais familiar, as famosas else leo, seria dado um alerta, caso contr-comparaes com valores numricos.echo As variveis so diferentes. rio a mensagem seria de incentivo.Veja a Tabela 3, e some s opes j Ateno: Os sinais de maior (>) noapresentadas os operadores da Tabela 4. incio das linhas internas ao if so osUfa! Como voc viu, tem coisa pra Executando o fragmento de programaprompts de continuao (que estochuchu, e o nosso if muito mais pode- acima, teremos como resultado:de nidos na varivel $PS2). Quando oroso que o dos outros. Vamos ver em shell identica que um comando con-uns exemplos como isso tudo funciona.As variveis so diferentes. tinuar na linha seguinte, automatica-Testamos a existncia de um diretrio:mente ele coloca este caractere, at queVamos agora alter-lo um pouco para o comando seja encerrado. if test -d lmb que a comparao seja numrica: Vamos mudar o exemplo para ver se o then programa continua funcionando:cd lmb cad1=1 elsecad2=01$ Familia=felinomkdir lmbif test $cad1 -eq $cad2$ Genero=gatocd lmb then $ if test $Familia = felino -o U echo As variveis so iguais.$Familia = canideo -a $Genero = U else ona -o $Genero = lobo Tabela 4 echo As variveis so diferentes. > then >echo Cuidado OperadorFinalidade > else Parnteses () 0E vamos execut-lo novamente: >echo Pode passar a mo> Exclamao !0 As variveis so iguais. Cuidado -a0 -o0Como voc viu, nas duas execues Obviamente a operao resultou emobtive resultados diferentes, porque aerro, porque a opo -a tem precedncia www.linuxmagazine.com.bredio 04 85 17. LINUX USER Papo de Botequimsobre a -o e, dessa, forma o que foi ava- Da mesma forma, para escolhermosmente a legibilidade, pois o comando ifliado primeiro foi a expresso: CDs que tenham a participao doir car com a sintaxe semelhante dasArtista1 e do Artista2, no necess-outras linguagens; por isso, esse ser o $Familia = canideo -a $Genero = Urio montar um if com o conector -o. O modo como o comando test ser usado ona egrep tambm resolve isso para ns. daqui para a frente.Veja como:Se voc pensa que acabou, est muitoQue foi avaliada como falsa, retor- enganado. Preste ateno Tabela Ver-nando o seguinte: $ egrep (Artista1|Artista2) U dade na Tabela 5.musicas $Familia = felino -o FALSO -o UTabela 5 - Tabela Verdade $Genero = lobo Ou (nesse caso especco) o prprioCombinao E OUgrep poderia nos quebrar o galho:VERDADEIRO-VERDADEIROTRUETRUEQue resolvida resulta em:VERDADEIRO-FALSO FALSE TRUE$grep Artista[12] musicas FALSO-VERDADEIRO FALSE TRUE VERDADEIRO -o FALSO -o FALSO FALSO-FALSOFALSE FALSE No egrep acima, foi usada umaComo agora todos os conectores soexpresso regular, na qual a barra ver- -o, e para que uma srie de expresses tical (|) trabalha como um ou lgico e Ou seja, quando o conector e e aconectadas entre si por diversos ou os parnteses so usados para limitar primeira condio verdadeira, o resul-lgicos seja verdadeira, basta que umaa amplitude deste ou. J no grep da tado nal pode ser verdadeiro ou falso,delas o seja. A expresso nal resultoulinha seguinte, a palavra Artista devedependendo da segunda condio; j nocomo VERDADEIRO e o then foi exe- ser seguida por um dos valores da lista conector ou, caso a primeira condiocutado de forma errada. Para que isso formada pelos colchetes ([]), isto , 1 ou 2. seja verdadeira, o resultado sempre servolte a funcionar faamos o seguinte: verdadeiro. Se a primeira for falsa, o resul- T legal, eu aceito o argumento, o if tado depender da segunda condio. $ if test ($Familia = felino Udo shell muito mais poderoso que Ora, os caras que desenvolveram o-o $Familia = canideo) -a Uos outros caretas - mas, c entre ns,interpretador no so bobos e esto ($Genero = ona -o $Genero = Uessa construo de if test ... muitosempre tentando otimizar ao mximo lobo) esquisita, pouco legvel. os algoritmos. Portanto, no caso do > then , voc tem razo, eu tambm noconector e, a segunda condio no ser >echo Cuidadogosto disso e acho que ningum gosta. avaliada, caso a primeira seja falsa, j > else Acho que foi por isso que o shell que o resultado ser sempre falso. J >echo Pode passar a moincorporou outra sintaxe, que substi- com o ou, a segunda ser executada > tui o comando test. somente caso a primeira seja falsa. Pode passar a mo Aproveitando-se disso, uma formaPara isso vamos pegar aquele exem-abreviada de fazer testes foi criada. ODesta forma, com o uso dos parn- plo para fazer uma troca de diretrios, conector e foi batizado de && e o ou de teses agrupamos as expresses com oque era assim:||. Para ver como isso funciona, vamos conector -o, priorizando a execuo eus-los como teste no nosso velho resultando em VERDADEIRO -a FALSO.if test ! -d lmb exemplo de troca de diretrio, que emPara que seja VERDADEIRO o resul-then sua ltima verso estava assim: tado de duas expresses ligadas pelo mkdir lmb conector -a, necessrio que ambas if [ ! -d lmb ] sejam verdadeiras, o que no o caso cd lmbthen do exemplo acima. Assim, o resultado mkdir lmb nal foi FALSO, sendo ento o else cor- e utilizando a nova sintaxe, vamos faz- retamente executado. lo assim:cd lmbSe quisermos escolher um CD que tenha faixas de 2 artistas diferentes, nosif [ ! -d lmb ]O cdigo acima tambm poderia ser sentimos tentados a usar um if com othen escrito de maneira abreviada: conector -a, mas sempre bom lembrarmkdir lmb que o bash nos oferece muitos recursos [ ! -d lmb ] && mkdir lmb e isso poderia ser feito de forma muito cd lmbcd dir mais simples com um nico comando grep, da seguinte forma: Ou seja, o comando test pode serTambm podemos retirar a negao (!):substitudo por um par de colchetes ([]), $ grep Artista1 musicas | grep U separados por espaos em branco dos[ -d lmb ] || mkdir lmb Artista2 argumentos, o que aumentar enorme-cd dir86edio 04 www.linuxmagazine.com.br 18. Papo de BotequimLINUX USERTabela 6 diretrio para dentro dele. Para execu-sempre estar dentro de lmb, desde que tar mais de um comando dessa forma,tenha permisso para entrar neste dire-Caractere Signicado necessrio fazer um grupamento detrio, permisso para criar um subdire-* Qualquer caractere ocorrendo zero ou comandos, o que se consegue com otrio dentro de ../lmb, que haja espaomais vezes? Qualquer caractere ocorrendo uma vez uso de chaves ({}). Veja como seria oem disco suciente...[...] Lista de caracteresmodo correto:Vejamos um exemplo didtico: depen-| ou lgico dendo do valor da varivel $opc o script cd lmb ||dever executar uma das opes a {seguir: incluso, excluso, alterao ou No primeiro caso, se o primeiro mkdir lmbencerrar sua execuo. Veja como ca-comando (o test, que est represen-cd lmb ria o cdigo:tado pelos colchetes) for bem sucedido,}isto , se o diretrio lmb no existir, o if [ $opc -eq 1 ]comando mkdir ser executado porqueAinda no est legal porque, caso othena primeira condio era verdadeira e o diretrio no exista, o cd exibir umainclusaoconector era e.mensagem de erro. Veja o modo certo: elif [ $opc -eq 2 ] No exemplo seguinte, testamos se o thendiretrio lmb existia (no anterior testa-cd lmb 2> /dev/null ||exclusaomos se ele no existia) e, caso isso fosse {elif [ $opc -eq 3 ]verdade, o mkdir no seria executado mkdir lmbthenporque o conector era ou. Outra formacd lmbalteracaode escrever o programa:}elif [ $opc -eq 4 ]thencd lmb || mkdir lmb Como voc viu, o comando if nos per- exitmitiu fazer um cd seguro de diversaselseNesse caso, se o comando cd fosse maneiras. sempre bom lembrar que o echo Digite uma opo entre Umal sucedido, o diretrio lmb seriaseguro a que me re ro diz respeito ao 1 e 4criado mas no seria feita a mudana de fato de que ao nal da execuo voc www.linuxmagazine.com.bredio 04 87 19. LINUX USERPapo de Botequim Quadro 1 - Scriptcase $opc in O comando date informa a data com-bem-educado1) inclusao ;;pleta do sistema e tem diversas opes 2) exclusao ;;de mascaramento do resultado. Neste #!/bin/bash 3) alteracao ;; comando, a formatao comea com # Programa bem educado que 4) exit ;;um sinal de mais (+) e os caracteres de # d bom-dia, boa-tarde ou *) echo Digite uma opo Uformatao vm aps um sinal de per- # boa-noite conforme a horaentre 1 e 4centagem (%), assim o %H signica a Hora=$(date +%H)esac hora do sistema. Dito isso, veja o exem- case $Hora in plo no Quadro 1.0? | 1[01]) echo Bom DiaComo voc deve ter percebido, eu Peguei pesado, n? Que nada, vamos;; usei o asterisco como ltima opo, istoesmiuar a resoluo:1[2-7]) echo Boa Tarde , se o asterisco atende a qualquer coisa,;; ento servir para qualquer coisa que0? | 1 [01] Zero seguido de qualquer* ) echo Boa Noite no esteja no intervalo de 1 a 4. Outra coisa (?), ou (|) um seguido de zero;; coisa a ser notada que o duplo ponto-e- ou um ([01]), ou seja, esta linha "casa" esac vrgula no necessrio antes do esac. com 01, 02, ... 09, 10 e 11; exit Vamos agora fazer um script mais1 [2-7] Signica um seguido da lista radical. Ele te dar bom dia, boa tarde de caracteres entre dois e sete, ou seja, Neste exemplo voc viu o uso do ou boa noite dependendo da hora emesta linha pega 12, 13, ... 17; comando elif como um substituto ouque for executado, mas primeiramente * Signica tudo o que no casou com forma mais curta de else if. Essa uma veja estes comandos:nenhum dos padres anteriores. sintaxe vlida e aceita, mas poderamos fazer ainda melhor. Para isso usamos o $ date Cara, at agora eu falei muito e bebi comando case, cuja sintaxe mostramos Tue Nov 9 19:37:30 BRST 2004pouco. Agora eu vou te passar um a seguir:$ date +%Hexerccio para voc fazer em casa e19me dar a resposta da prxima vez em case $var in que nos encontrarmos aqui no bote-padrao1) cmd1 quim, t legal? cmd2 Beleza! cmdn ;; o seguinte: faa um programa quepadrao2) cmd1 receba como parmetro o nome de cmd2 um arquivo e que quando executado cmdn ;;salve esse arquivo com o nome origi-padraon) cmd1 nal seguido de um til (~) e abra esse cmd2 arquivo dentro do vi para ser editado. cmdn ;;Isso para ter sempre uma cpia esac de backup do arquivo caso algumfaa alteraes indevidas. Obvia- Onde a varivel $var comparada aos mente, voc far as crticas neces- padres padrao1, ..., padraon. Caso um srias, como vericar se foi passado dos padres corresponda varivel, oum parmetro, se o arquivo indicado bloco de comandos cmd1, ..., cmdn cor- existe... En m, o que te der na telha e respondente executado at encontrarvoc achar que deva constar do script. um duplo ponto-e-vrgula (;;), quandoDeu pra entender? o uxo do programa ser interrompido Hum, hum... e desviado para instruo imediata- Chico, traz mais um, sem colarinho! mente aps o comando esac (que, caso no tenham notado, case ao contrrio.Julio Cezar Neves Ele indica o m do bloco de cdigo, daAnalista de Suportede Sistemas desdeSOBRE O AUTOR mesma forma que ot comando indica1969 e trabalha com o m de um if). Unix desde 1980, Na formao dos padres, so aceitos quando participou os caracteres mostrados na Tabela 6. do desenvolvimento Para mostrar como o cdigo ficado SOX, um sistemaoperacional similar ao Unix pro- melhor, vamos repetir o exemplo ante-duzido pela Cobra computadores. rior, s que desta vez usaremos o case Pode ser contatado no e-mail julio. em vez do tradicional bloco de [email protected] com if ... elif ... else ... .88 edio 04 www.linuxmagazine.com.br 20. Papo de BotequimLINUX USER Curso de Shell Script Papo de Botequim V Blocos de cdigo e laos (ou loops, como preferem alguns)Dave Hamilton - www.sxc.hu so o tema do ms em mais uma lio de nosso curso de Shell Script. Garom, salta uma boa redondinha, que t a m de refrescar o pensamento! POR JULIO CEZAR NEVES Fala cara! E as idias esto emordem? J fundiu a cuca ou vocainda agenta mais Shell?At agora j vimos alguns blocos decdigo, como quando te mostrei umexemplo para fazer um cd para dentroGento! T gostando muito! Gostei de um diretrio:tanto que at caprichei no exerccio Quadro 1: vira.sh$ cat vira.sh#!/bin/bash#que voc passou. Lembra que voc cd lmb 2> /dev/null || # vira - vi resguardandome pediu para fazer um programa{# arquivo anteriorque recebe como parmetro o nome mkdir lmb# Verica se algum parmetro foide um arquivo e que quando execu-cd lmb # passadotado salva esse arquivo com o nome }if [ $# -ne 1 ]original seguido de um til (~) e othenabre dentro do vi?O fragmento contido entre as duasecho Erro -> Uso: $0 U Claro que lembro, me mostre e expli- chaves ({}) forma um bloco de cdigo.que como voc fez.Tambm nesse exerccio que acabamosexit 1 Beleza, d uma olhada no quadro 1 de ver, em que salvamos o arquivo antes , beleza! Mas me diz uma coisa: por de edit-lo, existem vrios blocos deArq=$1que voc terminou o programa comcdigo compreendidos entre os coman-# Caso o arquivo no exista, noum exit 0?dos then e do if. Um bloco de cdigo# h cpia a ser salva Eu descobri que o nmero aps o tambm pode estar dentro de um case if [ ! -f $Arq ]exit indica o cdigo de retorno doou entre um do e um done. thenprograma (o $?, lembra?) e assim, Pera, Julio, que do e done so esses? vi $Arqcomo a execuo foi bem sucedida, No me lembro de voc ter falado exit 0ele encerra com o $?=0. Porm, se nisso, e olha que estou prestando voc observar, ver que caso o pro- muita ateno...# Se eu no puder alterar ograma no tenha recebido o nome do Pois , ainda no tinha falado porque#arquivo, vou usar o vi para que?arquivo ou caso o operador no tenhano havia chegado a hora certa. if [ ! -w $Arq ]permisso de gravao nesse arquivo,Todas as instrues de loop ou lao theno cdigo de retorno ($?) seria dife- executam os comandos do bloco com- echo Voc no tem permisso Urente do zero.preendidos entre um do e um done. Asde escrita em $Arq Grande garoto, aprendeu legal, mas instrues de loop ou lao so for, while exit 2bom deixar claro que exit 0, simples- e until , que sero explicadas uma amente exit ou no colocar exit produ- uma a partir de hoje. # J que est tudo OK, vouzem igualmente um cdigo de retorno # salvar a cpia e chamar o vi($?) igual a zero. Agora vamos falarO comando For cp -f $Arq $Arq~sobre as instrues de loop ou lao, Se voc est habituado a programar,vi $Arqmas antes vou passar o conceito decertamente j conhece o comando for,exit 0bloco de cdigo.mas o que voc no sabe que o for, www.linuxmagazine.com.bredio 0589 21. LINUX USERPapo de Botequim que uma instruo intrnseca do Shell Ento vamos execut-lo: $ echo $IFS | od -h (isso signica que o cdigo fonte do0000000 0920 0a0a comando faz parte do cdigo fonte do $ testefor10000004 Shell, ou seja, em bom programs umArqDoDOS.txt1:confuso:incusu: built-in), muito mais poderoso que oslogado:musexc:musicas:musinc: Isto , mandei a varivel (protegida seus correlatos das outras linguagens. muslist:$ da interpretao do Shell pelas aspas)Vamos entender a sua sintaxe, pri-para um dump hexadecimal (od -h). O meiro em portugus e, depois, como Como voc viu, o Shell transformouresultado pode ser interpretado com a funciona pra valer. Olhe s:o asterisco (que odeia ser chamado tabela abaixo: de asterstico) em uma lista de arqui-para var em val1 val2 ... valn vos separados por espaos em branco. Tabela 1: Resultado do od -hfaa Quando o for viu aquela lista, disse: cmd1 Opa, listas separadas por espaos Valor Hexadecimal Signicado cmd2comigo mesmo!09 cmdn O bloco de comandos a ser executado20feitoera somente o echo, que com a opo -n0a listou a varivel $Arq seguida de dois- Onde a varivel var assume cada umpontos (:), sem saltar a linha. O cifro dos valores da lista val1 val2 ... valn e, ($) do nal da linha da execuo o O ltimo 0a foi proveniente do para cada um desses valores, executa oprompt, que permaneceu na mesma dado ao nal do comando. bloco de comandos formado por cmd1, linha tambm em funo da opo -n.Para melhorar a explicao, vamos ver cmd2 e cmdn. Agora que j vimos o Outro exemplo simples (por enquanto):isso de outra forma: signicado da instruo em portugus, vejamos a sintaxe correta:$ cat testefor2 $ echo :$IFS: | cat -vet#!/bin/bash: ^I$ for var in val1 val2 ... valn# 2o. Programa didtico para :$ do # entender o forcmd1for Palavra in Linux Magazine U No comando cat, a opo -e repre-cmd2do Brasil senta o como um cifro ($)cmdndoe a opo -t representa o como doneecho $Palavraum ^I. Usei os dois-pontos (:) para mos-donetrar o incio e o m do echo. E dessa Vamos aos exemplos, para entenderforma, pudemos notar que os trs carac- direito o funcionamento deste comando.E executando temos:teres esto presentes naquela varivel. Vamos escrever um script para listar Agora veja voc: traduzindo, IFS sig- todos os arquivos do diretrio, separa-$ testefor2 nica separador entre campos. Uma vez dos por dois-pontos, mas antes veja isso:Linux entendido isso, eu posso a rmar que oMagazinecomando for no usa apenas listas sepa- $ echo * doradas por espaos em branco, mas sim ArqDoDOS.txt1 confuso incusu Brasilpelo contedo da varivel $IFS, cujo logado musexc musicas musinc valor padro so os caracteres que aca- muslist Como voc viu, esse exemplo bamos de ver. Para comprovarmos isso, to bobo e simples como o anterior,vamos continuar mexendo em nossa Isto , o Shell viu o asterisco (*),mas serve para mostrar o comporta- CDTeca, escrevendo um script que expandiu-o com o nome de todos os mento bsico do for. Veja s a fora dorecebe o nome do artista como parme- arquivos do diretrio e o comando echocomando: ainda estamos na primeira tro e lista as msicas que ele toca. Mas jogou-os para a tela separados por espa-possibilidade de sintaxe e j estou mos- primeiramente vamos ver como est o os em branco. Visto isso, vamos resol- trando novas formas de us-lo. L atrsnosso arquivo musicas: ver o problema a que nos propusemos:eu havia falado que o for usava listas separadas por espaos em branco, mas$ cat musicas $ cat testefor1 isso uma meia-verdade, s para facili-album 1^Artista1~Musica1: U #!/bin/bash tar a compreenso. Na verdade, as listasArtista2~Musica2 # 1o. Programa didtico parano so obrigatoriamente separadas poralbum 2^Artista3~Musica3: U # entender o forespaos. Mas antes de prosseguir, pre-Artista4~Musica4 for Arq in *ciso te mostrar como se comporta umaalbum 3^Artista5~Musica5: U dovarivel do sistema chamada de IFS, ouArtista6~Musica6echo -n $Arq:Inter Field Separator Veja no exemplo a album 4^Artista7~Musica7: U doneseguir seu contedo:Artista1~Musica390 edio 05 www.linuxmagazine.com.br 22. Papo de Botequim LINUX USERalbum 5^Artista9~Musica9: U o $1 seria Perereca e o resto desse lindo $ listartista Artista1Artista10~Musica10nome seria ignorado na pesquisa.Musica1Para que isso no ocorra, eu deveriaMusica3 Em cima desse leiaute desenvolve-passar o nome do artista entre aspasmos o script a seguir:() ou trocar $1 por $* (que representa Veja uma segunda sintaxe para o for:todos os parmetros passados), que $ cat listartistaa melhor soluo, mas nesse caso eu for var #!/bin/bashteria que modicar a crtica dos par-do # Dado um artista, mostra as metros e o grep. A nova verso no cmd1 # suas msicas seria se eu passei um parmetro, mas cmd2 if [ $# -ne 1 ]sim se passei pelo menos um par-cmdn then metro. Quanto ao grep, veja s o quedoneecho Voc deveria ter U aconteceria aps a substituio do $* passado um parmetro pelos parmetros: U, sem o in, como ele vai saber queexit 1valor assumir? Pois , n? Esta constru- echo $ArtMus | grep perereca U o, primeira vista, parece esquisita, IFS= & peteleca mas bastante simples. Neste caso, var : assumir um a um cada parmetro pas- for ArtMus in $(cut -f2 -d^ UIsso gera um erro. O correto : sado para o programa. Como exemplo musicas) para entender melhor, vamos fazer um doecho $ArtMus | grep -i U script que receba como parmetro umecho $ArtMus | grep $1 && U perereca & peteleca monte de msicas e liste seus autores: echo $ArtMus | cut -f2 -d~ done Aqui adicionamos a opo -i para$ cat listamusicaque a pesquisa ignorasse maisculas e #!/bin/bashO script, como sempre, comea tes-minsculas. As aspas foram inseridas# Recebe parte dos nomes detando se os parmetros foram passados para que o nome do artista fosse visto# msicas como parmetro ecorretamente, em seguida o IFS foi con-como uma s cadeia de caracteres. # lista os intrpretes. Se ogurado para e dois-pontos (:) Falta consertar o erro dele ter listado o # nome for composto, deve(como demonstram as aspas em linhas Artista10. O melhor dizer ao grep que a # ser passado entre aspas.diferentes), porque ele quem separa oscadeia de caracteres est no incio (^) de# ex. Eu no sou cachorro noblocos Artistan~Musicam. Desta forma, $ArtMus e que logo aps vem um til (~). # Churrasquinho de Mea varivel $ArtMus ir receber cada umpreciso redirecionar a sada do grep para / #desses blocos do arquivo (repare que odev/null para que os blocos no sejam lis-if [ $# -eq 0 ]for j recebe os registros sem o lbumtados. Veja a nova cara do programa:thenem virtude do cut na sua linha). Casoecho Uso: $0 musica1 Uencontre o parmetro ($1) no bloco, o$ cat listartista[musica2] ... [musican]segundo cut listar somente o nome da#!/bin/bash exit 1msica. Vamos executar o programa: # Dado um artista, mostra as # suas musicas IFS=$ listartista Artista1 # Versao 2 :Artista1~Musica1 if [ $# -eq 0 ]for MusicaMusica1then doArtista1~Musica3echo Voce deveria ter Uecho $MusicaMusica3passado pelo menos um parametro Str=$(grep -i $Musica UArtista10~Musica10exit 1musicas) ||Musica10 { IFS=echo No Upa! Aconteceram duas coisas inde-:encontradasejveis: os blocos tambm foram lista-for ArtMus in $(cut -f2 -d^ Ucontinuedos, e a Musica10 idem. Alm do mais,musicas) }o nosso arquivo de msicas est muitodofor ArtMus in $(echo $Str Usimples: na vida real, tanto a msica echo $ArtMus | grep -i U| cut -f2 -d^)quanto o artista tm mais de um nome. ^$*~ > /dev/null && echo U doSuponha que o artista fosse uma dupla$ArtMus | cut -f2 -d~echo $ArtMus | Usertaneja chamada Perereca & Petelecadone grep -i $Musica | cut -f1 -d~(no gosto nem de dar a idia com receio doneque isso se torne realidade). Nesse caso, O resultado :done www.linuxmagazine.com.br edio 0591 23. LINUX USERPapo de Botequim Da mesma forma que os outros, come- Ou na forma mais completa do seq:Repare que o incremento saiu do amos o exerccio com uma crtica sobrecorpo do for e passou para o bloco de os parmetros recebidos, em seguidafor i in $(seq 0 3 9) cdigo; repare tambm que, quando fizemos um for em que a varivel dousei o let, no foi necessrio iniciali- $Musica receber cada um dos parme-echo -n $i zar a varivel $i. Veja s os comandos a tros passados, colocando em $Str todos doneseguir, digitados diretamente no prompt, os lbuns que contm as msicas dese-0 3 6 9 para demonstrar o que acabo de falar: jadas. Em seguida, o outro for pega cada bloco Artista~Musica nos registros queA outra forma de fazer isso com $ echo $j esto em $Str e lista cada artista queuma sintaxe muito semelhante ao for da$ let j++ toca aquela msica. Vamos executar olinguagem C, como vemos a seguir: $ echo $j programa para ver se funciona mesmo:1for ((var=ini; cond; incr)) $ listamusica musica3 Musica4 Udo Ou seja, a varivel $j sequer existia eEginha Pocot cmd1no primeiro let assumiu o valor 0 (zero) musica3 cmd2para, aps o incremento, ter o valor 1. Artista3cmdnVeja s como as coisas cam simples: Artista1 done Musica4 for arq in * Artista4Onde var=ini signica que a vari-do Eginha Pocotvel var comear de um valor inicial let i++ No encontradaini; cond signica que o loop ou lao forecho $i -> $Arq ser executado enquanto var no atingir done A listagem cou feinha porque ainda a condio cond e incr signica o incre-1 -> ArqDoDOS.txt1 no sabemos formatar a sada; mas mento que a varivel var sofrer a cada 2 -> confuso qualquer dia desses, quando voc sou- passada do loop. Vamos aos exemplos:3 -> incusu ber posicionar o cursor, trabalhar com4 -> listamusica cores etc., faremos esse programa nova-for ((i=1; i listartista mente usando todas essas perfumarias.do 6 -> logado A esta altura dos acontecimentos, echo -n $i 7 -> musexc voc deve estar se perguntando: E done 8 -> musicas aquele for tradicional das outras lingua-1 2 3 4 5 6 7 8 99 -> musinc gens em que ele sai contando a partir 10 -> muslist de um nmero, com um determinadoA varivel i partiu do valor inicial 1, o 11 -> testefor1 incremento, at alcanar uma condi- bloco de cdigo (aqui somente o echo) 12 -> testefor2 o?. E a que eu te respondo: Eu ser executado enquanto i for menor ou no te disse que o nosso for mais por-igual ( /dev/null, como nosuma tremenda gata me esperando e do exemplos que vimos at agora.eu estava preso no trabalho sem poder sleep 30Vamos melhorar o nosso velhosair porque o meu chefe, que um p done musinc, nosso programa para incluirno saco (alis chefe-chato uma redun-echo O xato se mandou, no U registros no arquivo musicas, masdncia, n?), ainda estava na sala dele, hesite, d exit e v a lutaantes preciso te ensinar a pegarque ca bem na minha passagem para aum dado da tela, e j vou avisando:rua. Ele comeou a car cabreiro depoisAgora quero montar um script que s vou dar uma pequena dica doda quinta vez que passei pela sua portareceba o nome (e eventuais parme- comando read (que quem pega oe olhei para ver se j havia ido embora. tros) de um programa que ser execu- dado da tela), que seja o sucienteEnto voltei para a minha mesa e z, no tado em background e que me informepara resolver este nosso problema.servidor, um script assim: do seu trmino. Mas, para voc enten-Em uma outra rodada de chope vou der este exemplo, primeiro tenho dete ensinar tudo sobre o assunto,$ cat logaute.sh mostrar uma nova varivel do sistema.inclusive como formatar tela, mas#!/bin/bashVeja estes comandos executados direta- hoje estamos falando sobre loops. A# Espero que a Xuxa no tenhamente no prompt: sintaxe do comando read que nos# copyright de xefe e xato :) interessa por hoje a seguinte:while who | grep xefe$ sleep 10&do [1] 16317$ read -p "prompt de leitura" var sleep 30$ echo $!done 16317Onde prompt de leitura o textoecho O xato se mandou, no U [1]+ Done sleep 10 que voc quer que aparea escrito nahesite, d exit e v luta$ echo $!tela. Quando o operador teclar tal dado, 16317ele ser armazenado na varivel var. Neste scriptzinho, o comando while Por exemplo:testa o pipeline composto pelos coman-Isto , criei um processo em back-dos who e grep, que ser verdadeiroground que dorme por 10 segundos,$ read -p "Ttulo do lbum: " Titenquanto o grep localizar a palavrasomente para mostrar que a varivel $!xefe na sada do comando who. Destaguarda o PID (Process ID) do ltimo pro- Bem, uma vez entendido isso, vamosforma, o script dormir por 30 segundoscesso em background. Mas observe a especificao do nosso problema:enquanto o chefe estiver logado (Argh!). listagem e repare, aps a linha do Done, faremos um programa que inicialmenteAssim que ele se desconectar do servi- que a varivel reteve o valor mesmoler o nome do lbum e em seguida fardor, o uxo do script sair do loop e te aps o trmino desse processo. um loop de leitura, pegando o nome damostrar a to ansiada mensagem deBem, sabendo isso, j ca mais fcilmsica e o artista. Esse loop terminaliberdade. Mas quando executei o script, monitorar qualquer processo em back- quando for informada uma msica comadivinha o que aconteceu?ground. Veja s como:nome vazio, isto , quando o operador www.linuxmagazine.com.bredio 0687 26. LINUX USER Papo de BotequimDica until comando $cat chegada.sh Leitura de arquivo signica ler um a um do#!/bin/bash todos os registros, o que sempre uma cmd1 until who | grep julio operao lenta. Fique atento para no usar cmd2 do o while quando for desnecessrio. O Shell... sleep 30 tem ferramentas como o sed e a famlia cmdn done grep, que vasculham arquivos de forma doneecho $(date "+ Em %d/%m s U otimizada sem que seja necessrio o uso do%H:%Mh") > relapso.log while para faz-lo registro a registro.e dessa forma o bloco de comandos for-mado pelas instrues cmd1, cmd2,... eOlha que safado! O cara estava mon- der um simples . Para facili- cmdn executado at que a execuo datando um log com os meus horrios de tar a vida do operador, vamos oferecer instruo comando seja bem sucedida.chegada, e ainda por cima chamou o como default o mesmo nome do artista Como eu te disse, while e until funcio- arquivo de relapso.log! O que ser que da msica anterior (j que normal quenam de forma antagnica, e isso muito ele quis dizer com isso? o lbum seja todo do mesmo artista) atfcil de demonstrar: em uma guerra, Nesse script, o pipeline who | grep que ele deseje alter-lo. Veja na listagem sempre que se inventa uma arma, o julio, ser bem sucedido somente 1 como cou o programa.inimigo busca uma soluo para neu- quando julio for encontrado na sadaNosso exemplo comea com a lei- traliz-la. Foi baseado nesse principio do comando who, isto , quando eu tura do ttulo do lbum. Caso ele nobelicoso que meu chefe desenvolveu, nome logar no servidor. At que isso seja informado, terminamos a execu-mesmo servidor em que eu executava oacontea, o comando sleep, que forma o do programa. Em seguida um greplogaute.sh, um script para controlar oo bloco de instrues do until, colocar procura, no incio (^) de cada registromeu horrio de chegada. o programa em espera por 30 segun- de msicas, o ttulo informado seguido Um dia tivemos um problema na rede. dos. Quando esse loop encerrar-se, ser do separador (^) (que est precedido deEle me pediu para dar uma olhada no enviada uma mensagem para o arquivo uma contrabarra [] para proteg-lo da micro dele e me deixou sozinho na sala. relapso.log. Supondo que no dia 20/01 interpretao do Shell). Resolvi bisbilhotar os arquivos guerraeu me loguei s 11:23 horas, a mensa-Para ler os nomes dos artistas e as guerra e veja s o que descobri:gem seria a seguinte: msicas do lbum, foi montado um loop while simples, cujo nico destaque o Listagem 1 fato de ele armazenar o nome do intr- $ cat musinc.sh prete da msica anterior na varivel #!/bin/bash $oArt, que s ter o seu contedo alte- # Cadastra CDs (versao 4) rado quando algum dado for informado # para a varivel $Art, isto , quando no clear for teclado um simples ENTER para read -p "Ttulo do lbum: " Tit manter o artista anterior. [ "$Tit" ] || exit 1 # Fim da execuo se ttulo vazio O que foi visto at agora sobre o while if grep "^$Tit^" musicas > /dev/null foi muito pouco. Esse comando muito then utilizado, principalmente para leituraecho "Este lbum j est cadastrado" de arquivos, porm ainda nos faltaexit 1 bagagem para prosseguir. Depois que aprendermos mais sobre isso, veremos Reg="$Tit^" essa instruo mais a fundo. Cont=1O comando untiloArt= while true Este comando funciona de forma do idntica ao while, porm ao contrrio.echo "Dados da trilha $Cont:" Disse tudo mas no disse nada, n? read -p "Msica: " Mus o seguinte: ambos testam comandos;[ "$Mus" ] || break # Sai se vazio ambos possuem a mesma sintaxe eread -p "Artista: $oArt // " Art ambos atuam em loop; porm, o while[ "$Art" ] && oArt="$Art" # Se vazio Art anterior executa o bloco de instrues do loopReg="$Reg$oArt~$Mus:" # Montando registro enquanto um comando for bem suce-Cont=$((Cont + 1)) dido; j o until executa o bloco do loop# A linha anterior tb poderia ser ((Cont++)) at que o comando seja bem sucedido. done Parece pouca coisa, mas a diferena echo "$Reg" >> musicas fundamental. A sintaxe do comando sort musicas -o musicas praticamente a mesma do while. Veja:88edio 06 www.linuxmagazine.com.br 27. Papo de Botequim LINUX USEREm 20/01 s 11:23hAtalhos noloop Voltando nossa CDteca, quando Nem sempre um vamos cadastrar msicas seria idealciclo de programa,que pudssemos cadastrar diversoscompreendidoCDs de uma vez s. Na ltima versoentre um do e um do programa isso no ocorre: a cada CD done, sai pela portacadastrado o programa termina. Veja na da frente. Em algu- listagem 2 como melhor-lo.mas oportunidades, Nesta verso, um loop maior foi adi-temos que colocar cionado antes da leitura do ttulo, queum comando ques terminar quando a varivel $Para aborte de formadeixar de ser vazia. Caso o ttulo doc ont rolada esse lbum no seja informado, a vari- loop. De maneira Figura 1: A estrutura dos comandos break e continue, usados para contro-vel $Para receber um valor (coloqueiinversa, algumas lar o uxo de execuo em loops.1, mas poderia ter colocado qualquer vezes desejamoscoisa) para sair desse loop, terminandoque o f lu xo de pectivamente os comandos break (queo programa. No resto, o script idnticoexecuo do programa volte antes dej vimos rapidamente nos exemplos do verso anterior. chegar ao done. Para isso, temos res- comando while) e continue, que funcio-nam da forma mostrada na gura 1.Listagem 2O que eu no havia dito anterior-mente que nas suas sintaxes genricas$ cat musinc.sheles aparecem da seguinte forma:#!/bin/bash# Cadastra CDs (versao 5)break [qtd loop]#Para=e tambm:until [ "$Para" ]docontinue [qtd loop]clearread -p "Ttulo do lbum: " Tit Onde qtd loop representa a quanti-if [ ! "$Tit" ] # Se titulo vazio...dade dos loops mais internos sobre osthenquais os comandos iro atuar. Seu valor Para=1# Liguei ag de sadapor default 1.else Duvido que voc nunca tenha apa- if grep "^$Tit^" musicas > /dev/nullgado um arquivo e logo aps deu um thentabefe na testa se xingando porqueecho "Este lbum j est cadastrado"no devia t-lo removido. Pois , naexit 1dcima vez que z esta besteira, criei um script para simular uma lixeira, Reg="$Tit^"isto , quando mando remover um (ou Cont=1vrios) arquivo(s), o programa nge oArt=que deletou, mas no duro o que ele fez while [ "$Tit" ]foi mand-lo(s) para o diretrio /tmp/ doLoginName_do_usuario. Chamei esseecho Dados da trilha $Cont:programa de erreeme e no arquivo /etc/read -p "Msica: " Musprole coloquei a seguinte linha, que[ "$Mus" ] || break # Sai se vaziocria um apelido para ele:read -p "Artista: $oArt // " Art[ "$Art" ] && oArt="$Art" # Se vazio Art anterioralias rm=erreemeReg="$Reg$oArt~$Mus:" # Montando registroCont=$((Cont + 1))Veja o programa na listagem 3. Como# A linha anterior tb poderia ser ((Cont++))voc pode ver, a maior parte do script done formada por pequenas crticas aos echo "$Reg" >> musicasparmetros informados, mas como o sort musicas -o musicasscript pode ter recebido diversos arqui- vos a remover, a cada arquivo que nodonese encaixa dentro do especicado h www.linuxmagazine.com.br edio 0689 28. LINUX USER Papo de Botequim Listagem 3: erreeme.sh $ cat erreeme.shthen #!/bin/bash echo "$Arq nao existe." # Erro=3 # Salvando cpia de um arquivo antes de remov-lo continue # Volta para o comando for # Tem de ter um ou mais arquivos a remover if [ $# -eq 0 ]# Cmd. dirname informa nome do dir de $Arq then DirOrig=`dirname $Arq`echo "Erro -> Uso: erreeme arq [arq] ... [arq]" # Verica permisso de gravacao no diretrioecho "O uso de metacaracteres e permitido. Ex.Uif [ ! -w $DirOrig ] erreeme arq*"thenexit 1 echo "Sem permisso no diretorio de $Arq" Erro=4 continue# Volta para o comando for # Varivel do sistema que contm o nome do usurio. MeuDir="/tmp/$LOGNAME" # Se no existir o meu diretrio sob o /tmp... # Se estou "esvaziando a lixeira"... if [ ! -d $MeuDir ]if [ "$DirOrig" = "$MeuDir" ] then thenmkdir $MeuDir# Vou cri-lo echo "$Arq cara sem copia de seguranca" rm -i $Arq# Pergunta antes de remover # Ser que o usurio removeu? # Se no posso gravar no diretrio... [ -f $Arq ] || echo "$Arquivo removido" if [ ! -w $MeuDir ] continue thenecho "Impossivel salvar arquivos em $MeuDir. U Mude as permisses..." # Guardo no m do arquivo o seu diretrio originalUexit 2para us-lo em um script de undelete cd $DirOrig pwd >> $Arq # Varivel que indica o cod. de retorno do programa mv $Arq $MeuDir # Salvo e removo Erro=0echo "$Arq removido" # Um for sem o in recebe os parametros passadosdone for Arq do # Passo eventual nmero do erro para o cdigo # Se este arquivo no existir... # de retorno if [ ! -f $Arq ] exit $Erroum continue, para que a seqncia volte faa-o em casa e me traga para dis-um email para [email protected] o loop do for de forma a receber cutirmos no nosso prximo encontro com. Agora chega de papo que eu joutros arquivos.aqui no boteco.estou de goela seca de tanto falar. Me Quando voc est no Windows (com Poxa, mas nesse eu acho que vou dan- acompanha no prximo chope ou jperdo da m palavra) e tenta remover ar, pois no sei nem como comear...vai sair correndo para fazer o scriptaquele monte de lixo com nomes esqui- Cara, este programa como tudoque passei?sitos como HD04TG.TMP, se der erroo que se faz em Shell: extrema- Deixa eu pensar um pouco...em um dos arquivos os outros no somente fcil. para ser feito em, no Chico, traz mais um chope enquantoremovidos, no ? Ento, o continue foi mximo, 10 linhas. No se esqueaele pensa!usado para evitar que uma improprie-de que o arquivo est salvo em /tmp/dade dessas ocorra, isto , mesmo que $LOGNAME e que sua ltima linha Julio Cezar Neves Analista deSOBRE O AUTORd erro na remoo de um arquivo, o o diretrio em que ele residia antesSuporte de Sistemas desde 1969 e tra-programa continuar removendo osde ser removido. Tambm no sebalha com Unix desde 1980, quandooutros que foram passados.esquea de criticar se foi passado oparticipou do desenvolvimento do Eu acho que a esta altura voc devenome do arquivo a ser removido. SOX, um sistema operacional similar estar curioso para ver o programa eu vou tentar, mas sei no... ao Unix produzido pela Cobra Com-putadores. Pode ser contatado no que restaura o arquivo removido, no Tenha f, irmo, eu t te falando quee-mail [email protected] ? Pois ento a vai vai um desao: mole! Qualquer dvida s passar 90edio 06 www.linuxmagazine.com.br 29. Linux User Papo de botequim Papo de Botequim Curso de Shell ScriptParte VIIDave Hamilton - www.sxc.hu De pouco adianta ter acesso informao se ela no puder ser apresentada de forma atraente e que facilite a compreenso. O comando tput pode ser usado por shell scripts para posicionar caracteres e criar todos os tipos de efeito com o texto mostrado na tela. Garom, solta uma geladinha! por Julio Cezar Neves Cumequi, rapaz! Derreteu os pen- Pera, deixa eu ver se entendi o que voc , t vendo que o bichinho do shell tesamentos para fazer o scriptzinhofez: voc coloca na varivel Dir a ltimapegou. Vamos ver como ler dados, masque eu te pedi?linha do arquivo a ser restaurado, emantes vou te mostrar um comando que , eu realmente tive de colocar muita nosso caso /tmp/$LOGNAME/$1 (ondete d todas as ferramentas para formatar pensao na tela preta, mas acho que$LOGNAME o nome do usurio logado, uma tela de entrada de dados. nalmente consegui! Bem, pelo menose $1 o primeiro parmetro que voc nos testes que z a coisa funcionou, passou ao script), j que foi l que arma-O comando tput mas voc tem sempre que botar chifres zenamos o nome e caminho originais do O principal uso desse comando o posi- em cabea de cachorro!arquivo antes de mov-lo para o diretrio cionamento do cursor na tela. Alguns No bem assim. que programar em (de nido na varivel Dir). O comando parmetros podem no funcionar se o Shell Script muito fcil, mas o que grep -v apaga essa linha, restaurando modelo de terminal de nido pela vari- realmente importante so as dicas e o arquivo ao estado original, e o manda vel de ambiente $TERM no suport-los. macetes que no so triviais. As cor- de volta pra onde ele veio. A ltima linhaA tabela 1 apresenta apenas os principais rees que fao so justamente para o apaga da lixeira. Sensacional! Impe-parmetros e os efeitos resultantes, mas mostr-los. Mas vamos pedir dois cho- cvel! Nenhum erro! Viu? Voc j est existem muito mais deles. Para saber tudo pes enquanto dou uma olhadela no teupegando as manhas do shell! sobre o tput, veja a referncia [1]. script l na listagem 1. A Chico, traz Ento vamos l, chega de lesco-lescoVamos fazer um programa bem besta dois chopes! E no se esquea que ume bl-bl-bl, sobre o qu ns vamose fcil para ilustrar melhor o uso desse deles sem colarinho!falar hoje? comando. uma verso do famigeradoAl Mundo, s que dessa vez a fraseListagem 1 restaura.sh ser escrita no centro da tela e em vdeo reverso. Depois disso, o cursor voltar para 01 #!/bin/bash a posio original. Veja a listagem 2. 02 #Como o programa j est todo comen- 03 # Restaura arquivos deletados via erreeme tado, acho que a nica linha que precisa de 04 # explicao a 8, onde criamos a varivel 05 Coluna. O estranho ali aquele nmero 06 if [ $# -eq 0 ] 9, que na verdade indica o tamanho da 07 then cadeia de caracteres que vou escrever na 08echo "Uso: $0 " tela. Dessa forma, este programa somente 09exit 1 conseguiria centralizar cadeias de 9 carac- 10 fi teres, mas veja isto: 11 # Pega nome do arquivo/diretrio original na ltima linha 12 Dir=tail -1 /tmp/$LOGNAME/$1 $ var=Papo 13 # O grep -v exclui a ltima linha e recria o arquivo com o diretrio $ echo ${#var} 14 # e nome originalmente usados 4 15 grep -v $Dir /tmp/$LOGNAME/$1 > $Dir/$1 $ var="Papo de Botequim" 16 # Remove o arquivo que j estava moribundo $ echo ${#var} 17 rm /tmp/$LOGNAME/$1 1686 abril 2005 edio 07 www.linuxmagazine.com.br 30. Linux User Papo de botequim Tabela 1: Parmetros do tput e a linha 12 (echo $1) passaria a ser:ParmetroEfeito echo $*cup lin colCUrsor Position Posiciona o cursor na linha lin e coluna col. A origem (0,0) ca no canto superior esquerdo da tela. Lendo dados da telabold Coloca a tela em modo negritoBem, a partir de agora vamos aprenderrevColoca a tela em modo de vdeo reverso tudo sobre leitura. S no posso ensinara ler cartas e bzios porque se soubessesmso Idntico ao anteriorestaria rico, num pub Londrino tomandosmul Sublinha os caracteres um scotch e no em um boteco tomandoblinkDeixa os caracteres piscando chope. Mas vamos em frente.sgr0 Restaura a tela a seu modo normal Da ltima vez em que nos encontramosresetLimpa o terminal e restaura suas denies de acordo com terminfo, ou seja, o ter- eu dei uma palhinha sobre o comando minal volta ao comportamento padro denido pela varivel de ambiente $TERMread. Antes de entrarmos em detalhes,veja s isso:linesInforma a quantidade de linhas que compem a telacols Informa a quantidade de colunas que compem a tela $ read var1 var2 var3el Erase Line Apaga a linha a partir da posio do cursor Papo de Botequimed Erase Display Apaga a tela a partir da posio do cursor $ echo $var1Papoil n Insert Lines Insere n linhas a partir da posio do cursor$ echo $var2dl n Delete Lines Remove n linhas a partir da posio do cursordedch nDelete CHaracters Apaga n caracteres a partir da posio do cursor $ echo $var3sc Save Cursor position Salva a posio do cursor Botequimrc Restore Cursor position Coloca o cursor na posio marcada pelo ltimo sc$ read var1 var2Papo de Botequim$ echo $var1 Ahhh, melhorou! Ento agora sabemosessa construo devolve o nmero de Papo que a construo ${#variavel} devolvecaracteres do primeiro parmetro pas- $ echo $var2 a quantidade de caracteres da varivel.sado para o programa. Se o parmetrode Botequim Assim sendo, vamos otimizar o nossotivesse espaos em branco, seria preciso programa para que ele escreva em vdeo coloc-lo entre aspas, seno o $1 leva-Como voc viu, o read recebe uma reverso, no centro da tela (e indepen- ria em conta somente o pedao antes lista de parmetros separada por espa- dente do nmero de caracteres) a cadeiado primeiro espao. Para evitar esteos em branco e coloca cada item dessa de caracteres passada como parmetro e aborrecimento, s substituir o $1 por lista em uma varivel. Se a quantidade depois retorne o cursor posio em que $*, que como sabemos o conjunto dede variveis for menor que a quantidade estava antes da execuo do script. Veja todos os parmetros. Ento a linha 8de itens, a ltima varivel recebe o res- o resultado na listagem 3. caria assim: tante deles. Eu disse lista separada por Este script igual ao anterior, s queespaos em branco, mas agora que voc trocamos o valor xo na varivel Coluna # Centralizando a mensagem na tela j conhece tudo sobre o $IFS (Inter Field (9) por ${#1}, onde esse 1 $1, ou seja, Coluna=`$(((Colunas - ${#*}) / 2))`Separator Separador entre campos), queListagem 2: alo.sh Listagem 3: alo.sh mel