You are here:
Wiki-SL
>
TWikiBar Web
>
BatePapos
>
TWikiBarPapo002
(01 Aug 2009,
BrSalgado
)
(raw view)
E
dit
A
ttach
---+!! Papo de Botequim Parte II %TOC% - Garçom! Traz um "chops" e dois "pastel". O meu amigo hoje não vai beber por que ele finalmente está sendo apresentado a um verdadeiro sistema operacional e ainda tem muita coisa a aprender!%BR% - E então, amigo, tá entendendo tudo que te expliquei até agora?%BR% - Entendendo eu tô, mas não vi nada prático nisso...%BR% - Calma rapaz, o que te falei até agora, serve como base ao que há de vir daqui pra frente. Vamos usar estas ferramentas que vimos para montar programas estruturados, que o _Shell_ permite. Você verá porque até na TV já teve programa chamado "O _Shell_ é o Limite".%BR% - Para começar vamos falar dos comandos da família =grep=.%BR% - =grep=? Não conheço nenhum termo em inglês com este nome...%BR% - É claro, =grep= é um acrônimo *Global Regular Expression Print*, que usa expressões regulares para pesquisar a ocorrência de cadeias de caracteres na entrada definida (se bem que há uma lenda sobre como este comando foi nomeado: no editor de textos "ed", o avô do "vim", o comando usado para buscas era g/_expressao regular_/p, ou no inglês g/_re_/p.). Por falar em expressões regulares (ou *regexp*), o <a href="http://www.google.com.br/search?num=100&hl=pt-BR&as_qdr=all&q=%2B%22%5E+EXPRESS%C3%95ES+REGULARES+%24%22+%2Blego+%2B%22como+farejar+um+texto%22&btnG=Pesquisar&meta=" target="_blank">Aurélio Marinho Jargas</a> tem todas as dicas em sua página (inclusive tutorias) que abordam o tema. Se você está mesmo a fim de aprender a programar em *Shell*, *Perl*, *Python*, ... Acho bom você ler estes artigos para te ajudar no que está para vir. ---++ Eu fico com o =grep=, você com a gripe Esse negócio de gripe é brincadeira! É só um pretexto para pedir umas caipirinhas. Mas voltando à vaca fria, eu te falei que o =grep= procura cadeia de caracteres dentro de uma entrada definida, mas o que vem a ser uma "entrada definida"? Bem, existem várias formas de definir a entrada do comando =grep=. Vejamos: Pesquisando em um arquivo: %TERMINAL_INI% $ grep rafael /etc/passwd %TERMINAL_FIM% Pesquisando em vários arquivos: %TERMINAL_INI% $ grep grep *.sh %TERMINAL_FIM% Pesquisando na saida de comando: %TERMINAL_INI% $ who | grep Pelegrino %TERMINAL_FIM% No 1º exemplo, o mais simples, procurei a palavra rafael em qualquer lugar do arquivo =/etc/passwd=. Se quisesse procurá-la como um login name, isto é, somente no início dos registros deste arquivo, eu deveria fazer: %TERMINAL_INI% $ grep '^rafael' /etc/passwd %TERMINAL_FIM% E para que serve este circunflexo e os apóstrofos, você vai me perguntar. O circunflexo (=^=), se você tivesse lido os artigos anteriores sobre expressões regulares que te falei, saberia que servem para limitar a pesquisa ao início de cada linha, e os apóstrofos (='=) servem para o _Shell_ não interpretar este circunflexo, deixando-o passar incólume para o comando =grep=. Olha que legal! O =grep= aceita como entrada, a saída de outro comando redirecionado por um =pipe= (isto é muito comum em _Shell_ e é um tremendo acelerador de execução de comando já que atua como se a saída de um programa fosse guardada em disco e o segundo programa lesse este arquivo gerado), desta forma, no 3º exemplo, o comando =who= listou as pessoas "logadas" na mesma máquina que você (não se esqueça jamais: o _Linux_ é multiusuário) e o =grep= foi usado para verificar se o Pelegrino estava trabalhando ou "coçando". ---+++ A família =grep= Este comando =grep= é muito conhecido, pois é usado com muita freqüência, o que muitas pessoas desconhecem é que existem três comandos na família =grep=, que são: * =grep= * =egrep= * =fgrep= A principais características diferenciais entre os 3 são: * O =grep= pode ou não usar expressões regulares simples, porém no caso de não usá-las, o =fgrep= é melhor, por ser mais rápido; * O =egrep= ("e" de extended, extendido) é muito poderoso no uso de expressões regulares. Por ser o mais lento da família, só deve ser usado quando for necessária a elaboração de uma expressão regular não aceita pelo =grep=; * O =fgrep= ("f" de fast, rápido, ou de "file", arquivo) como o nome diz é o rapidinho da família, executa o serviço de forma muito veloz (por vezes é cerca de 30% mais veloz que o grep e 50% mais que o egrep), porém não permite o uso de expressões regulares na pesquisa. %ATENCAO_INI% Tudo que foi dito acima sobre velocidade, só se aplica à família de comandos =grep= do _Unix_. No _Linux_ o =grep= é sempre mais veloz, já que os outros dois (=fgrep= e =egrep=) são _scripts_ em _Shell_ que chamam o primeiro e, já vou adiantando, *não gosto* nem um pouquinho desta solução. %ATENCAO_FIM% - Agora que você já conhece as diferenças entre os membros da família, me diga: o que você acha dos três exemplos que eu dei antes das explicações?%BR% - Eu achei que o =fgrep= resolveria o teu problema de forma mais veloz do que o =grep=.%BR% - Perfeito! Tô vendo que você está atento! Está entendendo tudo que estou te explicando! Então vamos ver mais exemplos para clarear de vez as diferenças de uso dos membros da família. %BR% Exemplos Eu sei que em um arquivo existe um texto falando sobre =Linux= só não tenho certeza se está escrito com =L= maiúsculo ou =l= minúsculo. Posso fazer de duas formas: %TERMINAL_INI% $ egrep (Linux | linux) arquivo.txt %TERMINAL_FIM% ou %TERMINAL_INI% $ grep [Ll]inux arquivo.txt %TERMINAL_FIM% No primeiro caso, a expressão regular complexa ="(Linux | linux)"= usa os parênteses para agrupar as opções e a barra vertical (=|=) como um "ou" lógico, isto é, estou procurando =Linux= ou =linux=. No segundo, a expressão regular =[Ll]inux= significa: começado por =L= ou =l= seguido de =inux=. Por esta expressão ser mais simples, o =grep= consegue resolvê-la, portanto acho melhor usar a segunda forma, já que o =egrep= tornaria a pesquisa mais lenta. Outro exemplo. Para listar todos os subdiretórios do diretório corrente, basta: %TERMINAL_INI% $ ls -l | grep '^d'%OUT_INI% drwxr-xr-x 3 root root 4096 Dec 18 2000 doc drwxr-xr-x 11 root root 4096 Jul 13 18:58 freeciv drwxr-xr-x 3 root root 4096 Oct 17 2000 gimp drwxr-xr-x 3 root root 4096 Aug 8 2000 gnome drwxr-xr-x 2 root root 4096 Aug 8 2000 idl drwxrwxr-x 14 root root 4096 Jul 13 18:58 locale drwxrwxr-x 12 root root 4096 Jan 14 2000 lyx drwxrwxr-x 3 root root 4096 Jan 17 2000 pixmaps drwxr-xr-x 3 root root 4096 Jul 2 20:30 scribus drwxrwxr-x 3 root root 4096 Jan 17 2000 sounds drwxr-xr-x 3 root root 4096 Dec 18 2000 xine%OUT_FIM% %TERMINAL_FIM% No exemplo que acabamos de ver, o circunflexo (=^=) serviu para limitar a pesquisa à primeira posição da saída do =ls= longo. Os apóstrofos foram colocados para o _Shell_ não "ver" o circunflexo (=^=). Vamos ver mais um. Sabemos que as quatro primeiras posições possíveis de um =ls -l= de um arquivo comum (arquivo comum! Não é diretório, nem _link_, nem ...) devem ser: <center> %TABLE{ sort="off" tableborder="0" cellpadding="4" cellspacing="1" headerbg="#0000FF" headercolor="#FFFF00" databg="#BBBBBB,#DDDDDD" headerrows="2" footerrows="1" }% | *Posição* | * 1ª * | * 2ª * | * 3ª * | * 4ª * | | Valores Possíveis | =-= | =r= | =w= | =x= | |^| | =-= | =-= | =s= (suid) | |^| | | | =-= | </center> Assim sendo, para descobrir todos os arquivos executáveis em um determinado diretório eu deveria fazer: %TERMINAL_INI% $ ls -la | egrep '^-..(x|s)'%OUT_INI% -rwxr-xr-x 1 root root 2875 Jun 18 19:38 rc -rwxr-xr-x 1 root root 857 Aug 9 22:03 rc.local -rwxr-xr-x 1 root root 18453 Jul 6 17:28 rc.sysinit%OUT_FIM% %TERMINAL_FIM% Onde novamente usamos o circunflexo (=^=) para limitar a pesquisa ao início de cada linha, então as linhas listadas serão as que começam por um traço (=-=), seguido de qualquer coisa (o ponto quando usado como uma expressão regular significa qualquer coisa), novamente seguido de qualquer coisa, vindo a seguir um =x= ou um =s=. Obteríamos o mesmo resultado se fizéssemos: %TERMINAL_INI% $ ls -la | grep '^-..[xs]' %TERMINAL_FIM% e agilizaríamos a pesquisa. ---++ Vamos Montar uma "cdteca" Vamos começar a desenvolver programas, acho que a montagem de um banco de dados de músicas é bacana para efeito didático (e útil nesses tempos de _downloads_ de mp3 e "queimadores" de CDs). Não se esqueça que, da mesma forma que vamos desenvolver um monte de programas para organizar os seus CDs de música, com pequenas adaptações, você pode fazer o mesmo com os CDs de _software_ que vêm com a __Linux Magazine__ e outros que você compra ou queima, disponibilizando este banco de _software_ para todos que trabalham com você (o _Linux_ é multiusuário, e como tal deve ser explorado), desta forma ganhando muitos pontos com seu adorado chefe. - Péra ai! De onde eu vou receber os dados dos CDs? %BR% - Inicialmente, vou lhe mostrar como o seu programa pode receber parâmetros de quem o estiver executando e em breve, ensinarei a ler os dados pela tela ou de um arquivo. %BR% ---+++ Passando parâmetros O layout do arquivo musicas será o seguinte: =nome do álbum^intérprete1~nome da música1:..:intérprete~nome da música= isto é, o nome do álbum será separado por um circunflexo (=^=) do resto do registro, que é formado por diversos grupos compostos pelo intérprete de cada música do CD e a respectiva música interpretada. Estes grupos são separados entre si por dois-pontos (=:=) e internamente, o intérprete será separado por um til (=~=) do nome da música. Eu quero escrever um programa que chamado =musinc=, que incluirá registros no meu arquivo musicas. Eu passarei o conteúdo de cada álbum como parâmetro na chamada do programa fazendo assim: %TERMINAL_INI% $ musinc "álbum^interprete~musica:interprete~musica:..." %TERMINAL_FIM% Desta forma o programa =musinc= estará recebendo os dados de cada álbum como se fosse uma variável. A única diferença entre um parâmetro recebido e uma variável é que os primeiros recebem nomes numéricos (nome numérico fica muito esquisito, né? O que quis dizer é que seus nomes são formados por um e somente um algarismo), isto é =$1, $2, $3, ..., $9=. Vamos, antes de tudo, fazer um teste: Exemplos %TERMINAL_INI% $ cat teste %OUT_INI%#!/bin/bash # Programa para testar passagem de parametros echo "1o. parm -> $1" echo "2o. parm -> $2" echo "3o. parm -> $3"%OUT_FIM% %TERMINAL_FIM% Vamos executá-lo: %TERMINAL_INI% $ teste passando parametros para testar %OUT_INI%bash: teste: cannot execute%OUT_FIM% %TERMINAL_FIM% Ops! Esqueci-me de torná-lo executável. Vou fazê-lo de forma a permitir que todos possam executá-lo e em seguida vou testá-lo: %TERMINAL_INI% $ chmod 755 teste $ teste passando parametros para testar %OUT_INI%1o. parm -> passando 2o. parm -> parametros 3o. parm -> para%OUT_FIM% %TERMINAL_FIM% Repare que a palavra =testar=, que seria o quarto parâmetro, não foi listada. Isto deu-se justamente porque o programa teste só listava os três primeiros parâmetros. Vamos executá-lo de outra forma: %TERMINAL_INI% $ teste "passando parametros" para testar%OUT_INI% 1o. parm -> passando parametros 2o. parm -> para 3o. parm -> testar%OUT_FIM% %TERMINAL_FIM% As aspas não deixaram o =Shell= ver o espaço em branco entre as palavras e considerou-as um único parâmetro. ---+++ Macetes paramétricos Já que estamos falando em passagem de parâmetros deixa eu te dar mais umas dicas: <center> %TABLE{ sort="off" tableborder="0" cellpadding="4" cellspacing="1" headerbg="#0000FF" headercolor="#FFFF00" databg="#BBBBBB,#DDDDDD" headerrows="2" footerrows="1" }% | *Significado das Principais Variáveis Referentes aos Parâmetros* || | *Variável* | *Significado* | | =$0= | Contém o nome do programa | | =$#= | Contém a quantidade de parâmetros passados | | =$*= | Contém o conjunto de todos os parâmetros (muito parecido com =$@=) | </center> Exemplos Vamos alterar o programa =teste= para usar as variáveis que acabamos de ver. Vamos fazê-lo assim: %TERMINAL_INI% $ cat teste %OUT_INI%#!/bin/bash # Programa para testar passagem de parametros (2a. Versao) echo O programa $0 recebeu $# parametros echo "1o. parm -> $1" echo "2o. parm -> $2" echo "3o. parm -> $3" echo Todos de uma só \"tacada\": $*%OUT_FIM% %TERMINAL_FIM% Repare que antes das aspas eu usei uma barra invertida para o escondê-las da interpretação do _Shell_ (se não usasse as contrabarras as aspas não apareceriam). Vamos executá-lo: %TERMINAL_INI% $ teste passando parametros para testar %OUT_INI%O programa teste recebeu 4 parametros 1o. parm -> passando 2o. parm -> parametros 3o. parm -> para Todos de uma só "tacada": passando parametros para testar%OUT_FIM% %TERMINAL_FIM% Conforme eu disse, os parâmetros recebem números de =1= a =9=, mas isso não significa que não posso usar mais de 9 parâmetros significa somente que só posso endereçar 9. Vamos testar isso: Exemplo: %TERMINAL_INI% $ cat teste %OUT_INI%#!/bin/bash # Programa para testar passagem de parametros (3a. Versao) echo O programa $0 recebeu $# parametros echo "11o. parm -> $11" shift echo "2o. parm -> $1" shift 2 echo "4o. Parm -> $1"%OUT_FIM% %TERMINAL_FIM% Vamos executá-lo: %TERMINAL_INI% $ teste passando parametros para testar %OUT_INI%O programa teste recebeu 4 parametros que são: 11o. parm -> passando1 2o. parm -> parametros 4o. parm -> testar%OUT_FIM% %TERMINAL_FIM% Duas coisas muito interessantes neste _script_: 1 Para mostrar que os nomes dos parâmetros variam de =$1= a =$9= eu fiz um echo =$11= e o que aconteceu? O _Shell_ interpretou como sendo =$1= seguido do algarismo =1= e listou =passando1=; 1 O comando =shift= cuja sintaxe é =shift n=, podendo o =n= assumir qualquer valor numérico (porém seu _default_ é =1= como no exemplo dado), despreza os =n= primeiros parâmetros, tornando o parâmetro de ordem =n+1=, o primeiro ou seja, o =$1=. Bem, agora que você já sabe mais sobre passagem de parâmetros do que eu, vamos voltar à nossa "cdteca" para fazer o _script_ de inclusão de CDs no meu banco chamado =musicas=. O programa é muito simples (como tudo em _Shell_) e vou listá-lo para você ver: Exemplos %TERMINAL_INI% $ cat musinc %OUT_INI%#!/bin/bash # Cadastra CDs (versao 1) # echo $1 >> musicas%OUT_FIM% %TERMINAL_FIM% O _script_ é fácil e funcional, limito-me a anexar ao fim do arquivo =musicas= o parâmetro recebido. Vamos cadastrar 3 álbuns para ver se funciona (para não ficar "enchendo lingüiça", vou supor que em cada CD só existem 2 músicas): %TERMINAL_INI% $ musinc "album 3^Artista5~Musica5:Artista6~Musica5" $ musinc "album 1^Artista1~Musica1:Artista2~Musica2" $ musinc "album 2^Artista3~Musica3:Artista4~Musica4" %TERMINAL_FIM% Listando o conteúdo de musicas. %TERMINAL_INI% $ cat musicas %OUT_INI%album 3^Artista5~Musica5:Artista6~Musica6 album 1^Artista1~Musica1:Artista2~Musica2 album 2^Artista3~Musica3:Artista4~Musica4%OUT_FIM% %TERMINAL_FIM% Não está funcional como achava que deveria ficar... podia ter ficado melhor. Os álbuns estão fora de ordem, dificultando a pesquisa. Vamos alterar nosso _script_ e depois testá-lo novamente: %TERMINAL_INI% $ cat musinc %OUT_INI%#!/bin/bash # Cadastra CDs (versao 2) # echo $1 >> musicas sort musicas -o musicas%OUT_FIM% %TERMINAL_FIM% Vamos cadastrar mais um: %TERMINAL_INI% $ musinc "album 4^Artista7~Musica7:Artista8~Musica8" %TERMINAL_FIM% Agora vamos ver o que aconteceu com o arquivo =musicas=: %TERMINAL_INI% $ cat musicas %OUT_INI%album 1^Artista1~Musica1:Artista2~Musica2 album 2^Artista3~Musica3:Artista4~Musica4 album 3^Artista5~Musica5:Artista6~Musica5 album 4^Artista7~Musica7:Artista8~Musica8%OUT_FIM% %TERMINAL_FIM% Simplesmente inseri uma linha que classifica o arquivo =musicas= dando a saída nele mesmo (para isso serve a opção =-o=), após cada álbum ser anexado. Oba! Agora está legal e quase funcional. Mas atenção, não se desespere! Esta não é a versão final. O programa ficará muito melhor e mais amigável, em uma nova versão que desenvolveremos após aprendermos a adquirir os dados da tela e formatar a entrada. Exemplos Ficar listando com o comando =cat= não está com nada, vamos então fazer um programa chamado =muslist= para listar um álbum cujo nome será passado como parâmetro: %TERMINAL_INI% $ cat muslist %OUT_INI%#!/bin/bash # Consulta CDs (versao 1) # grep $1 musicas%OUT_FIM% %TERMINAL_FIM% Vamos executá-lo, procurando pelo =album 2=. Como já vimos antes, para passar a cadeia =album 2= é necessário protegê-la da interpretação do _Shell_, para que ele não a interprete como dois parâmetros. Vamos fazer assim: %TERMINAL_INI% $ muslist "álbum 2" %OUT_INI%grep: can't open 2 musicas: album 1^Artista1~Musica1:Artista2~Musica2 musicas: album 2^Artista3~Musica3:Artista4~Musica4 musicas: album 3^Artista5~Musica5:Artista6~Musica6 musicas: album 4^Artista7~Musica7:Artista8~Musica8%OUT_FIM% %TERMINAL_FIM% Que lambança! Onde está o erro? Eu tive o cuidado de colocar o parâmetro passado entre aspas, para o _Shell_ não dividi-lo em dois! É, mas repare como está o =grep= executado: =grep $1 musicas= Mesmo colocando =álbum 2= entre aspas, para que fosse encarado como um único parâmetro, quando o =$1= foi passado pelo _Shell_ para o comando =grep=, transformou-se em dois argumentos. Desta forma o conteúdo final da linha, que o comando =grep= executou foi o seguinte: =grep album 2 musicas= Como a sintaxe do =grep= é: =grep <cadeia de caracteres> [arq1, arq2, ..., arqn]= o =grep= entendeu que deveria procurar a cadeia de caracteres =album= nos =arquivos 2= e =musicas=, Por não existir o =arquivo 2= gerou o erro, e por encontrar a palavra =album= em todos os registros de =musicas=, listou a todos. %DICA_INI% Sempre que a =cadeia de caracteres= a ser passada para o comando =grep= possuir brancos ou =TAB=, mesmo que dentro de variáveis, coloque-a sempre entre aspas para evitar que as palavras após o primeiro espaço em branco ou =TAB= sejam interpretadas como nomes de arquivos. %DICA_FIM% Por outro lado, é melhor ignorarmos maiúsculas e minúsculas na pesquisa. Resolveríamos os dois problemas se o programa tivesse a seguinte forma: %TERMINAL_INI% $ cat muslist %OUT_INI%#!/bin/bash # Consulta CDs (versao 2) # grep -i "$1" musicas%OUT_FIM% %TERMINAL_FIM% Neste caso, usamos a opção =-i= do =grep=, que como já vimos, serve para ignorar maiúsculas e minúsculas, e colocamos o =$1= entre aspas, para que o =grep= continuasse a ver a cadeia de caracteres resultante da expansão da linha pelo =Shell= como um único argumento de pesquisa. %TERMINAL_INI% $ muslist "album 2"%OUT_INI% album2^Artista3~Musica3:Artista4~Musica4%OUT_FIM% %TERMINAL_FIM% Agora repare que o =grep= localiza a cadeia pesquisada em qualquer lugar do registro, então da forma que estamos fazendo, podemos pesquisar por álbum, por música, por intérprete ou até por um pedaço de qualquer um destes. Quando conhecermos os comandos condicionais, montaremos uma nova versão de =muslist= que permitirá especificar por qual campo pesquisar. Aí você vai me dizer: - Poxa, mas é um saco ter que colocar o argumento de pesquisa entre aspas na hora de passar o nome do álbum. Esta forma não é nem um pouco amigável! %BR% - Tem razão, e por isso vou te mostrar uma outra forma de fazer o que você pediu: %BR% %TERMINAL_INI% $ cat muslist %OUT_INI%#!/bin/bash # Consulta CDs (versao 3) # grep -i "$*" musicas $ muslist album 2 album 2^Artista3~Musica3:Artista4~Musica4%OUT_FIM% %TERMINAL_FIM% Desta forma, o =$*=, que significa todos os parâmetros, será substituído pela cadeia =album 2= (de acordo com o exemplo anterior, fazendo o que você queria. Não se esqueça o problema do _Shell_ não é se você pode ou não fazer uma determinada coisa. O problema é decidir qual é a melhor forma de fazê-la, já que para desempenhar qualquer tarefa, a quantidade de opções é enorme. Ah! Em um dia de verão você foi à praia, esqueceu o CD no carro, aquele "solzinho" de 40 graus empenou o seu CD e agora você precisa de uma ferramenta para removê-lo do banco de dados? Não tem problema, vamos desenvolver um _script_ chamado =musexc=, para excluir estes CDs. Antes de desenvolver o "bacalho", quero te apresentar a uma opção bastante útil da família de comandos =grep=. É a opção =-v=, que quando usada lista todos os registros da entrada, exceto o(s) localizado(s) pelo comando. Vejamos: Exemplos %TERMINAL_INI% $ grep -v "album 2" musicas %OUT_INI%album 1^Artista1~Musica1:Artista2~Musica2 album 3^Artista5~Musica5:Artista6~Musica6 album 4^Artista7~Musica7:Artista8~Musica8%OUT_FIM% %TERMINAL_FIM% Conforme eu expliquei antes, o =grep= do exemplo listou todos os registros de musicas exceto o referente a =album 2=, porque atendia ao argumento do comando. Estamos então prontos para desenvolver o _script_ para remover aquele CD empenado da sua "CDteca". Ele tem a seguinte cara: %TERMINAL_INI% $ cat musexc %OUT_INI%#!/bin/bash # Exclui CDs (versao 1) # grep -v "$1" musicas > /tmp/mus$$ mv -f /tmp/mus$$ musicas%OUT_FIM% %TERMINAL_FIM% Na primeira linha mandei para =/tmp/mus$$= o arquivo musicas, sem os registros que atendessem a consulta feita pelo comando =grep=. Em seguida, movi (que, no duro, equivale a renomear) =/tmp/mus$$= por cima do antigo =musicas=. Usei o arquivo =/tmp/mus$$= como arquivo de trabalho, porque como já havia citado no artigo anterior, o =$$= contém o =PID= (_Process Identification_ ou identificação do processo) e desta forma cada um que editar o arquivo =musicas= o fará em um arquivo de trabalho diferente, desta forma evitando colisões no uso. - Aê cara, estes programas que fizemos até aqui estão muito primários em virtude da falta de ferramentas que ainda temos. Mas é bom, enquanto eu tomo mais um chope, você ir para casa praticar em cima dos exemplos dados porque, eu prometo, chegaremos a desenvolver um sistema bacana para controle dos seus CDs. %BR% - Quando nos encontrarmos da próxima vez, vou te ensinar como funcionam os comandos condicionais e aprimoraremos mais um pouco estes _scripts_. %BR% - Por hoje chega! Já falei demais e preciso molhar a palavra porque estou de goela seca! %BR% - Garçom! Mais um sem colarinho! Vou aproveitar também para mandar o meu jabá: diga para os amigos que quem estiver afim de fazer um curso porreta de programação em _Shell_ que mande um e-mail para a nossa <a href="mailto:contato@clavis.com.br?Subject=Curso de Shell com Julio Neves">gerencia de treinamento</a> para informar-se. Qualquer dúvida ou falta de companhia para um chope ou até para falar mal dos políticos é só mandar um e-mail para <a href="mailto:julioneves@openoffice.org?Subject=Dúvidas Papo de Botequim">mim</a>. Valeu!
E
dit
|
A
ttach
|
P
rint version
|
H
istory
: r23
<
r22
<
r21
<
r20
<
r19
|
B
acklinks
|
V
iew topic
|
M
ore topic actions
Topic revision: r23 - 01 Aug 2009 - 22:30:40 -
BrSalgado
TWikiBar
Página Inicial
Últimas alterações
Índice
Procurar
Estatísticas de Uso
Aviso de Atualização
Configurações Gerais
Projeto Gráfico
Mapa do Site
Quem Somos
Registre-se
?
Regras de Formatação
Biblioteca Gráfica
?
Carinhas Gráficas
Webs Wiki-SL
Amadeu
Anapolivre
ArquivoLivre
Arte
BahiaSocial
BeaBa
BibliotecaLivre
Blogs
BrasilDigital
BrasilELivre
BSM
Ccsa
CESL
CoberturaWiki
Cooperativas
Curriculo
DarvinMarosin
DiaD
Dinamicoop
Economia
EconomiaSolidaria
EducacaoLivre
Ekaaty
Emacsbr
ENSL
Fatos
Festival3
Festival4
Flisol
Fmpb
Formatos
Foswikibr
FSM2005
GNOMEBR
GTTemario2004
GTWeb
Guialivre
HDC
Incubus
InkscapeBrasil
Jogos
KdeBR
KSP
LGM
LinuxStokDoc
Livros
Main
Mentores
MHHOB
MinuanoDigital
MoradiaECidadania
OlhosDagua
Olimpo
OLPC
OOPTQ
Papers
PCLivre
PentahoBrasil
Pessoas
Portal
Prefeituras
PSLAL
PSLBA
PSLBancarios
PSLBrasil
PSLGO
PSLMA
PSLMG
PSLMIP
PSLMT
PSLMulheres
PSLPI
PubFisl10
PubFisl7
PubFisl8
PubFisl9
QuilomboDoSopapo
RadioSL
RedeMesh
RedePopular
RobotWars
Sandbox
Saudelivre
Scribus
Sementes
Shakya
SLRJ
SoftwareLivreIrece
SoftwareLivreVS
SoLiSC
SuporteLivre
System
Telecentros
TeseSA
TextoLivre
TV
TWikiBar
TWikiPtbr
UNELivre
UNIMIX
VilaTorres
WebNordeste
WTRD2004
Este Menu
?skin=free
English
Español
Português brasileiro
Copyright © by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding Wiki-SL?
Send feedback