0% acharam este documento útil (0 voto)
0 visualizações55 páginas

Curso de Shell Script

Enviado por

6k25lwfd8
Direitos autorais
© All Rights Reserved
Levamos muito a sério os direitos de conteúdo. Se você suspeita que este conteúdo é seu, reivindique-o aqui.
Formatos disponíveis
Baixe no formato PDF, TXT ou leia on-line no Scribd
0% acharam este documento útil (0 voto)
0 visualizações55 páginas

Curso de Shell Script

Enviado por

6k25lwfd8
Direitos autorais
© All Rights Reserved
Levamos muito a sério os direitos de conteúdo. Se você suspeita que este conteúdo é seu, reivindique-o aqui.
Formatos disponíveis
Baixe no formato PDF, TXT ou leia on-line no Scribd

LINUX USER Papo de Botequim

Curso de Shell Script

Papo de Botequim
Você não agüenta mais aquele seu porque, em inglês, Shell significa con-
cha, carapaça, isto é, fica entre o u-
amigo usuário de Linux enchendo o suário e o sistema operacional, de
forma que tudo que interage com
seu saco com aquela história de que o o sistema operacional, tem que
passar pelo seu crivo.
sistema é fantástico e o Shell é uma

ferramenta maravilhosa? A partir


O ambiente Shell
Bom já que para chegar ao
desta edição vai ficar mais fácil en- núcleo do Linux, no seu ker-
nel que é o que interessa a
tender o porquê deste entusiasmo... todo aplicativo, é necessária a
filtragem do Shell, vamos enten-
POR JULIO CEZAR NEVES der como ele funciona de forma a
tirar o máximo proveito das inú-
meras facilidades que ele nos oferece.

D
iálogo entreouvido em uma mesa O Linux, por definição, é um sistema
de um botequim, entre um multiusuário – não podemos nunca nos
usuário de Linux e um empur- esquecer disto – e para permitir o acesso
rador de mouse: O ambiente Linux de determinados usuários e barrar a en-
• Quem é o Bash? Para você entender o que é e como fun- trada de outros, existe um arquivo cha-
• É o filho caçula da família Shell. ciona o Shell, primeiro vou te mostrar mado /etc/passwd, que além de fornecer
• Pô cara! Estás a fim de me deixar como funciona o ambiente em camadas dados para esta função de “leão-de-chá-
maluco? Eu tinha uma dúvida e você do Linux. Dê uma olhada no gráfico cara” do Linux, também provê informa-
me deixa com duas! mostrado na Figura 1. ções para o início de uma sessão (ou
• Não, maluco você já é há muito tem- Neste gráfico podemos ver que a ca- “login”, para os íntimos) daqueles que
po: desde que decidiu usar aquele sis- mada de hardware é a mais profunda e é passaram por esta primeira barreira. O
tema operacional que você precisa formada pelos componentes físicos do último campo de seus registros informa
reiniciar dez vezes por dia e ainda por seu computador. Em torno dela, vem a ao sistema qual é o Shell que a pessoa
cima não tem domínio nenhum sobre camada do kernel que é o cerne do vai receber ao iniciar sua sessão.
o que esta acontecendo no seu com- Linux, seu núcleo, e é quem põe o hard- Lembra que eu te falei de Shell, fa-
putador. Mas deixa isso prá lá, pois ware para funcionar, fazendo seu geren- mília, irmão? Pois é, vamos começar a
vou te explicar o que é Shell e os com- ciamento e controle. Os programas e entender isto: o Shell é a conceituação
ponentes de sua família e ao final da comandos que envolvem o kernel, dele de concha envolvendo o sistema opera-
nossa conversa você dirá: “Meu Deus se utilizam para realizar as tarefas para cional propriamente dito, é o nome
do Shell! Porque eu não optei pelo que foram desenvolvidos. Fechando tudo genérico para tratar os filhos desta idéia
Linux antes?”. isso vem o Shell, que leva este nome que, ao longo dos muitos anos de exis-

Quadro 1: Uma rapidinha nos principais sabores de Shell


Bourne Shell (sh): Desenvolvido por Stephen do sh e a elas agregou muitas outras. A com- C Shell (csh): Desenvolvido por Bill Joy, da
Bourne do Bell Labs (da AT&T, onde também patibilidade total com o sh vem trazendo Universidade de Berkley, é o Shell mais uti-
foi desenvolvido o Unix), foi durante muitos muitos usuários e programadores de Shell lizado em ambientes BSD. Foi ele quem intro-
anos o Shell padrão do sistema operacional para este ambiente. duziu o histórico de comandos. A
Unix. É também chamado de Standard Shell Boune Again Shell (bash): Desenvolvido ini- estruturação de seus comandos é bem simi-
por ter sido durante vários anos o único, e é cialmente por Brian Fox e Chet Ramey, este é lar à da linguagem C. Seu grande pecado foi
até hoje o mais utilizado. Foi portado para o Shell do projeto GNU. O número de seus ignorar a compatibilidade com o sh, partindo
praticamente todos os ambientes Unix e dis- adeptos é o que mais cresce em todo o por um caminho próprio.
tribuições Linux. mundo, seja por que ele é o Shell padrão do Além destes Shells existem outros, mas irei
Korn Shell (ksh): Desenvolvido por David Linux, seja por sua grande diversidade de falar somente sobre os três primeiros, tratan-
Korn, também do Bell Labs, é um supercon- comandos, que incorpora inclusive diversos do-os genericamente por Shell e assinalando
junto do sh, isto é, possui todas as facilidades comandos característicos do C Shell. as especificidades de cada um.

82 Agosto 2004 [Link]


Papo de Botequim LINUX USER

tência do sistema operacional Unix, redirecionamento, que pode ser de


foram aparecendo. Atualmente existem
Com que Shell eu vou? entrada (stdin), de saída (stdout) ou dos
Quando digo que o último campo do arqui-
diversos sabores de Shell (veja Quadro 1 erros (stderr), conforme vou explicar a
vo /etc/passwd informa ao sistema qual é o
na página anterior). seguir. Mas antes precisamos falar de...
Shell que o usuário vai usar ao se “logar”, isto
deve ser interpretado ao pé-da-letra. Se este
Como funciona o Shell campo do seu registro contém o termo prog, Substituição de Variáveis
O Shell é o primeiro programa que você ao acessar o sistema o usuário executará o Neste ponto, o Shell verifica se as even-
ganha ao iniciar sua sessão (se quiser- programa prog. Ao término da execução, a tuais variáveis (parâmetros começados
mos assassinar a língua portuguesa sessão do usuário se encerra automatica- por $), encontradas no escopo do
mente. Imagine quanto se pode incremen-
podemos também dizer “ao se logar”) no comando, estão definidas e as substitui
tar a segurança com este simples artifício.
Linux. É ele quem vai resolver um monte por seus valores atuais.
de coisas de forma a não onerar o kernel
com tarefas repetitivas, poupando-o para volvidos (inclusive o próprio programa), Substituição de Meta-
tratar assuntos mais nobres. Como cada e retorna um erro caso o usuário que Caracteres
usuário possui o seu próprio Shell inter- chamou o programa não esteja autor- Se algum meta-caracter (ou “coringa”,
pondo-se entre ele e o Linux, é o Shell izado a executar esta tarefa. como *, ? ou []) for encontrado na linha
quem interpreta os comandos digitados e de comando, ele será substituído por
examina as suas sintaxes, passando-os $ ls linux seus possíveis valores.
esmiuçados para execução. linux Supondo que o único item no seu
• Êpa! Esse negócio de interpretar co- diretório corrente cujo nome começa
mando não tem nada a ver com inter- Neste exemplo o Shell identificou o ls co- com a letra n seja um diretório chamado
pretador não, né? mo um programa e o linux como um pa- nomegrandeprachuchu, se você fizer:
• Tem sim: na verdade o Shell é um in- râmetro passado para o programa ls.
terpretador que traz consigo uma po- $ cd n*
derosa linguagem com comandos de Atribuição
alto nível, que permite construção de Se o Shell encontra dois campos separa- como até aqui quem está manipulando a
loops, de tomadas de decisão e de ar- dos por um sinal de igual (=) sem espa- linha de comando ainda é o Shell e o
mazenamento de valores em variáveis, ços em branco entre eles, ele identifica programa cd ainda não foi executado, o
como vou te mostrar. esta seqüência como uma atribuição. Shell expande o n* para nomegrandepra-
• Vou explicar as principais tarefas que o chuchu (a única possibilidade válida) e
Shell cumpre, na sua ordem de exe- $ valor=1000 executa o comando cd com sucesso.
cução. Preste atenção, porque esta
ordem é fundamental para o entendi- Neste caso, por não haver espaços em Entrega da linha de comando
mento do resto do nosso bate papo. branco (que é um dos caracteres reserva- para o kernel
dos), o Shell identificou uma atribuição e Completadas todas as tarefas anteriores,
Análise da linha de comando colocou 1000 na variável valor. o Shell monta a linha de comando, já
Neste exame o Shell identifica os carac- com todas as substituições feitas e
teres especiais (reservados) que têm sig- Resolução de chama o kernel para executá-la em um
nificado para a interpretação da linha e Redirecionamentos novo Shell (Shell filho), que ganha um
logo em seguida verifica se a linha pas- Após identificar os componentes da li- número de processo (PID ou Process
sada é um comando ou uma atribuição nha que você digitou, o Shell parte para IDentification) e fica inativo, tirando
de valores, que são os ítens que vou a resolução de redirecionamentos. uma soneca durante a execução do pro-
descrever a seguir. O Shell tem incorporado ao seu elenco grama. Uma vez encerrado este processo
de habilidades o que chamamos de (e o Shell filho), o “Shell pai” recebe
Comando novamente o controle e exibe um
Quando um comando é digi- “prompt”, mostrando que está pronto
tado no “prompt” (ou linha de Shell para executar outros comandos.
comando) do Linux, ele é divi-
dido em partes, separadas por
Programas e Comandos Cuidado na Atribuição
espaços em branco: a primeira Núcleo ou Kernel Jamais faça:
parte é o nome do programa,
cuja existência será verificada; Hardware $ valor = 1000
bash: valor: not found
em seguida, nesta ordem, vêm
Neste caso, o Bash achou a palavra valor iso-
as opções/parâmetros, redire-
lada por espaços e julgou que você estivesse
cionamentos e variáveis.
mandando executar um programa chama-
Quando o programa identifi-
do valor, para o qual estaria passando dois
cado existe, o Shell verifica as parâmetros: = e 1000.
permissões dos arquivos en- Figura 1: Ambiente em camadas de um sistema Linux

[Link] Agosto 2004 83


LINUX USER Papo de Botequim

Decifrando a Pedra de Roseta $ echo \* esperando pelo teclado (Entrada Padrão)


Para tirar aquela sensação que você tem $ echo * e como também não citei a saída, o que
quando vê um script Shell, que mais eu teclar irá para a tela (Saída Padrão),
parece uma sopa de letrinhas ou um con- Viu a diferença? criando desta forma – como eu havia
junto de hieróglifos, vou lhe mostrar os • Aspas (“): exatamente iguais ao após- proposto – um programa gago. Experi-
principais caracteres especiais para que trofo, exceto que, se a cadeia entre mente!
você saia por aí como Champollion deci- aspas contiver um cifrão ($), uma
frando a Pedra de Roseta. crase (`), ou uma barra invertida (\), Redirecionamentop da Saída
estes caracteres serão interpretados Padrão
Caracteres para remoção do pelo Shell. Para especificarmos a saída de um pro-
significado. Não precisa se estressar, eu não te dei grama usamos o símbolo “>” ou o
É isso mesmo, quando não desejamos exemplos do uso das aspas por que “>>”, seguido do nome do arquivo pa-
que o Shell interprete um caractere você ainda não conhece o cifrão ($) ra o qual se deseja mandar a saída.
específico, devemos “escondê-lo” dele. nem a crase (`). Daqui para frente - Vamos transformar o programa ante-
Isso pode ser feito de três maneiras difer- veremos com muita constância o uso rior em um “editor de textos”:
entes, cada uma com sua peculiaridade: destes caracteres especiais; o mais
• Apóstrofo (´): quando o Shell vê uma importante é entender seu significado. $ cat > Arq
cadeia de caracteres entre apóstrofos,
ele retira os apóstrofos da cadeia e não Caracteres de O cat continua sem ter a entrada especi-
interpreta seu conteúdo. redirecionamento ficada, portanto está aguardando que os
A maioria dos comandos tem uma entra- dados sejam teclados, porém a sua saída
$ ls linuxm* da, uma saída e pode gerar erros. Esta está sendo desviada para o arquivo Arq.
linuxmagazine entrada é chamada Entrada Padrão ou Assim sendo, tudo que esta sendo tecla-
$ ls 'linuxm*' stdin e seu dispositivo padrão é o teclado do esta indo para dentro de Arq, de for-
bash: linuxm* no such file U do terminal. Analogamente, a saída do ma que fizemos o editor de textos mais
or directory comando é chamada Saída Padrão ou curto e ruim do planeta.
stdout e seu dispositivo padrão é a tela Se eu fizer novamente:
No primeiro caso o Shell “expandiu” o do terminal. Para a tela também são
asterisco e descobriu o arquivo linux- enviadas normalmente as mensagens de $ cat > Arq
magazine para listar. No segundo, os erro oriundas dos comandos, chamada
apóstrofos inibiram a interpretação do neste caso de Saída de Erro Padrão ou Os dados contidos em Arq serão perdi-
Shell e veio a resposta que não existe o stderr. Veremos agora como alterar este dos, já que antes do redirecionamento o
arquivo linuxm*. estado de coisas. Shell criará um Arq vazio. Para colocar
• Contrabarra ou Barra Invertida (\): i- Vamos fazer um programa gago. Para mais informações no final do arquivo eu
dêntico aos apóstrofos exceto que a isto digite (tecle “Enter” ao final de cada deveria ter feito:
barra invertida inibe a interpretação linha – comandos do usuário são ilus-
somente do caractere que a segue. trados em negrito): $ cat >> Arq
Suponha que você, acidentalmente,
tenha criado um arquivo chamado * $ cat Redirecionamento da Saída
(asterisco) – o que alguns sabores de E-e-eu sou gago. Vai encarar? de Erro Padrão
Unix permitem – e deseja removê-lo. E-e-eu sou gago. Vai encarar? Assim como por padrão o Shell recebe os
Se você fizesse: dados do teclado e envia a saída para a
O cat é um comando que lista o con- tela, os erros também vão para a tela se
$ rm * teúdo do arquivo especificado para a você não especificar para onde eles de-
Saída Padrão (stdout). Caso a entrada vem ser enviados. Para redirecionar os
Você estaria na maior encrenca, pois o não seja definida, ele espera os dados da erros, use 2> SaidaDeErro. Note que en-
rm removeria todos os arquivos do stdin (a entrada padrão). Ora como eu tre o número 2 e o sinal de maior (>)
diretório corrente. A melhor forma de não especifiquei a entrada, ele a está não existe espaço em branco.
fazer o serviço é: Vamos supor que durante a execução
Redirecionamento Perigoso de um script você pode, ou não (depen-
$ rm \* Como já havia dito, o Shell resolve a linha e dendo do rumo tomado pela execução
depois manda o comando para a execução. do programa), ter criado um arquivo
Desta forma, o Shell não interpreta o Assim, se você redirecionar a saída de um chamado /tmp/seraqueexiste$$. Como
asterisco, evitando a sua expansão. arquivo para ele próprio, primeiramente o não quer ficar com sujeira no disco
Faça a seguinte experiência científica: Shell “esvazia”este arquivo e depois manda rígido, ao final do script você coloca a
o comando para execução! Desta forma, linha a seguir:
para sua alegria, você acabou de perder o
$ cd /etc
conteúdo de seu querido arquivo.
$ echo '*' rm /tmp/seraqueexiste$$

84 Agosto 2004 [Link]


Papo de Botequim LINUX USER

caprichamos, né? Então ao invés de sair


Dados ou Erros? redigindo o mail direto no “prompt”, de
Etiquetas Erradas
Preste atenção! Não confunda >> com 2>. O forma a tornar impossível a correção de Um erro comum no uso de labels (como o
primeiro anexa dados ao final de um arqui- fimftp do exemplo anterior) é causado pela
uma frase anterior onde, sem querer,
vo, e o segundo redireciona a Saída de Erro presença de espaços em branco antes ou
você escreveu um “nós vai”, você edita
Padrão (stderr) para um arquivo que está após o mesmo. Fique muito atento quanto a
um arquivo com o conteúdo da mensa-
sendo designado. Isto é importante! isso, por que este tipo de erro costuma dar
gem e após umas quinze verificações
uma boa surra no programador, até que seja
sem constatar nenhum erro, decide
detectado. Lembre-se: um label que se preze
Caso o arquivo não existisse seria envi- enviá-lo e para tal faz:
tem que ter uma linha inteira só para ele.
ado para a tela uma mensagem de erro.
Para que isso não aconteça faça: $ mail chefe@[Link] < U
arquivocommailparaochefe nada a partir deste ponto até encontrar
rm /tmp/seraqueexiste$$ 2> U o ‘label’ fimftp. Você não entenderia
/dev/null e o chefe receberá uma mensagem com o droga nenhuma, já que são instruções
conteúdo do arquivocommailparaochefe. específicas do ftp”.
Para que você teste a Saída de Erro Pa- Outro tipo de redirecionamento “muito Se fosse só isso seria simples, mas
drão direto no prompt do seu Shell, vou louco” que o Shell permite é o chamado pelo próprio exemplo dá para ver que
dar mais um exemplo. Faça: “here document”. Ele é representado por existem duas variáveis ($Usuario e
<< e serve para indicar ao Shell que o $Senha), que o Shell vai resolver antes
$ ls naoexiste escopo de um comando começa na linha do redirecionamento. Mas a grande
bash: naoexiste no such file U seguinte e termina quando encontra uma vantagem deste tipo de construção é
or directory linha cujo conteúdo seja unicamente o que ela permite que comandos tam-
$ ls naoexiste 2> arquivodeerros “label” que segue o sinal <<. bém sejam interpretados dentro do
$ Veja o fragmento de script a seguir, escopo do “here document”, o que,
$ cat arquivodeerros com uma rotina de ftp: aliás, contraria o que acabei de dizer.
bash: naoexiste no such file U Logo a seguir te explico como esse
or directory ftp -ivn hostremoto << fimftp negócio funciona. Agora ainda não dá,
user $Usuario $Senha estão faltando ferramentas.
Neste exemplo, vimos que quando fize- binary • O comando user é do repertório de
mos um ls em naoexiste, ganhamos uma get arquivoremoto instruções do ftp e serve para passar o
mensagem de erro. Após redirecionar a fimftp usuário e a senha que haviam sido
Saída de Erro Padrão para arquivodeerros lidos em uma rotina anterior a este
e executar o mesmo comando, recebe- neste pedacinho de programa temos um fragmento de código e colocados res-
mos somente o “prompt” na tela. Quan- monte de detalhes interessantes: pectivamente nas duas variáveis:
do listamos o conteúdo do arquivo para • As opções usadas para o ftp (-ivn) $Usuario e $Senha.
o qual foi redirecionada a Saída de Erro servem para ele listar tudo que está • O binary é outra instrução do ftp, que
Padrão, vimos que a mensagem de erro acontecendo (opção -v de “verbose”), serve para indicar que a transferência
tinha sido armazenada nele. para não ficar perguntando se você de arquivoremoto será feita em modo
É interessante notar que estes carac- tem certeza que deseja transmitir cada binário, isto é o conteúdo do arquivo
teres de redirecionamento são cumula- arquivo (opção -i de “interactive”) e não será inteerpretado para saber se
tivos, isto é, se no exemplo anterior finalmente a opção -n serve para dizer está em ASCII, EBCDIC, …
fizéssemos o seguinte: ao ftp para ele não solicitar o usuário e • O comando get arquivoremoto diz ao
sua senha, pois estes serão informados cliente ftp para pegar este arquivo no
$ ls naoexiste 2>> U pela instrução específica (user); servidor hostremoto e trazê-lo para a
arquivodeerros • Quando eu usei o << fimftp, estava nossa máquina local. Se quiséssemos
dizendo o seguinte para o interpreta- enviar um arquivo, bastaria usar, por
a mensagem de erro oriunda do ls seria dor: “Olha aqui Shell, não se meta em exemplo, o comando put arquivolocal.
anexada ao final de arquivodeerros.
Direito de Posse Redirecionamento de
Redirecionamento da O $$ contém o PID,isto é,o número do seu comandos
Entrada Padrão processo. Como o Linux é multiusuário,é Os redirecionamentos de que falamos até
Para fazermos o redirecionamento da En- bom anexar sempre o $$ ao nome dos seus agora sempre se referiam a arquivos, isto
trada Padrão usamos o < (menor que). arquivos para não haver problema de propri- é, mandavam para arquivo, recebiam de
“E pra que serve isso?”, você vai me per- edade,isto é,caso você batizasse o seu ar- arquivo, simulavam arquivo local, … O
guntar. Deixa eu dar um exemplo, que quivo simplesmente como seraqueexiste,a que veremos a partir de agora, redirecio-
você vai entender rapidinho. primeira pessoa que o usasse (criando-o na a saída de um comando para a entra-
então) seria o seu dono e a segunda ganharia
Suponha que você queira mandar um da de outro. É utilíssimo e, apesar de não
um erro quando tentasse gravar algo nele.
mail para o seu chefe. Para o chefe nós ser macaco gordo, sempre quebra os

[Link] Agosto 2004 85


LINUX USER Papo de Botequim

maiores galhos. Seu nome é “pipe” (que $ echo "Existem who | wc -l U $ (pwd ; cd /etc ; pwd)
em inglês significa tubo, já que ele cana- usuarios conectados" /home/meudir
liza a saída de um comando para a Existem who | wc -l usuarios U /etc
entrada de outro) e sua representação é a conectados $ pwd
| (barra vertical). /home/meudir
Hi! Olha só, não funcionou! É mesmo,
$ ls | wc -l não funcionou e não foi por causa das “Quequeiiisso” minha gente? Eu estava
21 aspas que eu coloquei, mas sim por que no /home/meudir, mudei para o /etc,
eu teria que ter executado o who | wc -l constatei que estava neste diretório com
O comando ls passou a lista de arquivos antes do echo. Para resolver este proble- o pwd seguinte e quando o agrupamento
para o comando wc, que quando está ma, tenho que priorizar a segunda parte de comandos terminou, eu vi que conti-
com a opção -l conta a quantidade de li- do comando com o uso de crases: nuava no /etc/meudir!
nhas que recebeu. Desta forma, pode- Hi! Será que tem coisa do mágico
mos afirmar categoricamente que no $ echo "Existem `who | wc -l` U Mandrake por aí? Nada disso. O interes-
meu diretório existiam 21 arquivos. usuarios conectados" sante do uso de parênteses é que eles
Existem 8 usuarios U invocam um novo Shell para executar os
$ cat /etc/passwd | sort | lp conectados comandos que estão em seu interior.
Desta forma, fomos realmente para o
A linha de comandos acima manda a Para eliminar esse monte de brancos diretório /etc, porém após a execução de
listagem do arquivo /etc/passwd para a antes do 8 que o wc -l produziu, basta todos os comandos, o novo Shell que
entrada do comando sort. Este a classi- retirar as aspas. Assim: estava no diretório /etc morreu e retor-
fica e envia para o lp que é o gerenciador namos ao Shell anterior que estava em
da fila de impressão. $ echo Existem `who | wc -l` U /home/meudir.
usuarios conectados Que tal usar nossos novos conceitos?
Caracteres de ambiente Existem 8 usuarios conectados
Quando queremos priorizar uma expres- $ mail suporte@[Link] << FIM
são, nós a colocamos entre parênteses, As aspas protegem da interpretação do Ola suporte, hoje as `date U
não é? Pois é, por causa da aritmética é Shell tudo que está dentro dos seus lim- “+%hh:mm”` ocorreu novamente U
normal pensarmos deste jeito. Mas em ites. Como para o Shell basta um espaço aquele problema que eu havia U
Shell o que prioriza mesmo são as crases em branco como separador, o monte de reportado por telefone. De U
(`) e não os parênteses. Vou dar exemp- espaços será trocado por um único após acordo com seu pedido segue a U
los para você entender melhor. a retirada das aspas. listagem do diretorio:
Eu quero saber quantos usuários estão Outra coisa interessante é o uso do `ls -l`
“logados” no computador que eu admi- ponto-e-vírgula. Quando estiver no Shell, Abracos a todos.
nistro. Eu posso fazer: você deve sempre dar um comando em FIM
cada linha. Para agrupar comandos em
$ who | wc -l uma mesma linha, temos que separá-los Finalmente agora podemos demonstrar o
8 por ponto-e-vírgula. Então: que conversamos anteriormente sobre
“here document”. Os comandos entre
O comando who passa a lista de usuários $ pwd ; cd /etc; pwd ;cd -;pwd crases tem prioridade, portanto o Shell
conectados ao sistema para o comando /home/meudir os executará antes do redirecionamento
wc -l, que conta quantas linhas recebeu e /etc do “here document”. Quando o suporte
mostra a resposta na tela. Muito bem, /home/meudir receber a mensagem, verá que os
mas ao invés de ter um número oito comandos date e ls foram executados
solto na tela, o que eu quero mesmo é Neste exemplo, listei o nome do diretório antes do comando mail, recebendo então
que ele esteja no meio de uma frase. Ora, corrente com o comando pwd, mudei um instantâneo do ambiente no
para mandar frases para a tela eu só pre- para o diretório /etc, novamente listei o momento de envio do email.
ciso usar o comando echo; então vamos nome do diretório e finalmente voltei pa- - Garçom, passa a régua! ■
ver como é que fica: ra o diretório onde estava anteriormente
(cd -), listando seu nome. Repare que Julio Cezar Neves é Analista de Su-
SOBRE O AUTOR

Buraco Negro coloquei o ponto-e-vírgula de todas as porte de Sistemas desde 1969 e tra-
Em Unix existe um arquivo fantasma. formas possíveis, para mostrar que não balha com Unix desde 1980, quando
Chama-se /dev/[Link] que é enviado importa se existem espaços em branco fez parte da equipe que desenvolveu
para este arquivo some. Assemelha-se a um antes ou após este caracter. o SOX, sistema operacional, similar
Buraco Negro. No caso do exemplo, como ao Unix, da Cobra Computadores. É
Finalmente, vamos ver o caso dos
não me interessava guardar a possível men- professor do curso de Mestrado em
parênteses. No exemplo a seguir, colo-
sagem de erro oriunda do comando rm, redi- Software Livre das Faculdades Estácio
camos diversos comandos separados por
recionei-a para este arquivo. de Sá, no Rio de Janeiro.
ponto-e-vírgula entre parênteses:

86 Agosto 2004 [Link]


Papo de Botequim LINUX USER

Curso de Shell Script

Papo de Botequim - Parte II


Nossos personagens voltam à mesa do bar para discutir expressões regulares e linhas que usavam a palavra grep, em
todos os arquivos terminados em .sh.
colocar a “mão na massa” pela primeira vez, construindo um aplicativo simples Como uso essa extensão para definir
meus arquivos com programas em Shell,
para catalogar uma coleção de CDs. POR JÚLIO CÉSAR NEVES malandramente, o que fiz foi listar as lin-
has dos programas que poderia usar
como exemplo do comando grep.
arçom! Traz um “chops” e dois Olha que legal! O grep aceita como

G “pastel”. O meu amigo hoje não


vai beber porque está finalmente
sendo apresentado a um verdadeiro sis-
entrada a saída de outro comando, redi-
recionado por um pipe (isso é muito
comum em Shell e é um tremendo
tema operacional, e ainda tem muita acelerador da execução de coman-
coisa a aprender! dos). Dessa forma, no 3° exemplo,
– E então, amigo, tá entendendo o comando who listou as pessoas
tudo que te expliquei até agora? “logadas” na mesma máquina que
– Entendendo eu tô, mas não vi você (não se esqueça jamais: o
nada prático nisso… Linux é multiusuário) e o grep foi
– Calma rapaz, o que te falei até usado para verificar se o Carvalho
agora serve como base ao que há estava trabalhando ou “coçando”.
de vir daqui pra frente. Vamos usar O grep é um comando muito con-
essas ferramentas que vimos para hecido, pois é usado com muita fre-
montar programas estruturados. Você qüência. O que muitas pessoas não
verá porque até na TV já teve pro- sabem é que existem três comandos na
grama chamado “O Shell é o Limite”. família grep: grep, egrep e fgrep. A princi-
Para começar vamos falar dos coman- pais diferenças entre os 3 são:
dos da família grep • grep - Pode ou não usar expressões
– Grep? Não conheço nenhum termo em $ grep franklin /etc/passwd regulares simples, porém no caso de
inglês com este nome… não usá-las, o fgrep é melhor, por ser
– É claro, grep é um acrônimo (sigla) Pesquisando em vários arquivos: mais rápido.
para Global Regular Expression Print, • egrep (“e” de extended, estendido) - É
que usa expressões regulares para $ grep grep *.sh muito poderoso no uso de expressões
pesquisar a ocorrência de cadeias de regulares. Por ser o mais poderoso dos
caracteres na entrada definida. Pesquisando na saída de um comando: três, só deve ser usado quando for
Por falar em expressões regulares (ou necessária a elaboração de uma
regexp), o Aurélio Marinho Jargas es- $ who | grep carvalho expressão regular não aceita pelo grep.
creveu dois artigos [1 e 2] imperdíveis • fgrep (“f” de fast, rápido) - Como o
para a Revista do Linux sobre esse No 1º exemplo, procurei a palavra nome diz, é o ligeirinho da família,
assunto e também publicou um livro [3] franklin em qualquer lugar do arquivo executando o serviço de forma muito
pela Editora Novatec. Acho bom você ler /etc/passwd. Se quisesse procurar um veloz (por vezes é cerca de 30% mais
esses artigos, eles vão te ajudar no que nome de usuário, isto é, somente no iní- rápido que o grep e 50% mais que o
está para vir. cio dos registros desse arquivo, poderia egrep), porém não permite o uso de
digitar $ grep ‘^franklin’ /etc/passwd. expressões regulares na pesquisa.
Eu fico com grep,você com gripe “E para que servem o circunflexo e os –Agora que você já conhece as difer-
Esse negócio de gripe é brincadeira, só apóstrofos?”, você vai me perguntar. Se enças entre os membros da família, me
um pretexto para pedir umas caipirinhas. tivesse lido os artigos que mencionei, diga: o que você acha dos três exemplos
Eu te falei que o grep procura cadeias de saberia que o circunflexo serve para limi- que eu dei antes das explicações?
caracteres dentro de uma entrada defi- tar a pesquisa ao início de cada linha e – Achei que o fgrep resolveria o teu prob-
nida, mas o que vem a ser uma “entrada os apóstrofos servem para o Shell não lema mais rapidamente que o grep.
definida”? Bem, existem várias formas interpretar esse circunflexo, deixando-o – Perfeito! Tô vendo que você está
de definir a entrada do comando grep. passar incólume para o comando grep. atento, entendendo tudo que estou te
Veja só. Para pesquisar em um arquivo: No 2º exemplo mandei listar todas as explicando! Vamos ver mais exemplos

[Link] Setembro 2004 87


LINUX USER Papo de Botequim

Quadro 1 - Listando subdiretórios ser explorado).


– Péra aí! De onde eu vou receber os
$ ls -l | grep ‘^d’ dados dos CDs?
drwxr-xr-x 3 root root 4096 Dec 18 2000 doc – Vou mostrar como o programa pode
drwxr-xr-x 11 root root 4096 Jul 13 18:58 freeciv receber parâmetros de quem o estiver
drwxr-xr-x 3 root root 4096 Oct 17 2000 gimp executando e, em breve, ensinarei a ler
drwxr-xr-x 3 root root 4096 Aug 8 2000 gnome os dados da tela ou de um arquivo.
drwxr-xr-x 2 root root 4096 Aug 8 2000 idl
drwxrwxr-x 14 root root 4096 Jul 13 18:58 locale Passando parâmetros
drwxrwxr-x 12 root root 4096 Jan 14 2000 lyx Veja abaixo a estrutura do arquivo con-
drwxrwxr-x 3 root root 4096 Jan 17 2000 pixmaps tendo a lista das músicas:
drwxr-xr-x 3 root root 4096 Jul 2 20:30 scribus
drwxrwxr-x 3 root root 4096 Jan 17 2000 sounds nomedoálbum^intérprete1~nomeU
drwxr-xr-x 3 root root 4096 Dec 18 2000 xine damúsica1:...:intérpreten~nomeU
drwxr-xr-x 3 root root 4096 Jun 19 2000 xplns damúsican

para clarear de vez as diferenças de -l). Os apóstrofos foram usados para o Isto é, o nome do álbum será separado
uso entre os membros da família. Shell não “ver” o circunflexo. Vamos ver por um circunflexo do resto do registro,
Eu sei que em um arquivo qualquer mais um. Veja na Tabela 1 as quatro formado por diversos grupos compostos
existe um texto falando sobre Linux, só primeiras posições possíveis da saída de pelo intérprete de cada música do CD e a
não tenho certeza se está escrito com L um ls -l em um arquivo comum (não é música interpretada. Estes grupos são
maiúsculo ou minúsculo. Posso fazer diretório, nem link, nem …). separados entre si por dois pontos (:) e,
uma busca de duas formas: Para descobrir todos os arquivos exe- internamente, o intérprete será separado
cutáveis em um determinado diretório por um til (~) do nome da música.
egrep (Linux | linux) [Link] eu poderia fazer: Quero escrever um programa chamado
musinc, que incluirá registros no meu
ou então: $ ls -la | egrep ‘^-..(x|s)’ arquivo músicas. Passarei cada álbum
como parâmetro para o programa:
grep [Ll]inux [Link] novamente usamos o circunflexo para
limitar a pesquisa ao início de cada $ musinc “álbum^interprete~U
No primeiro caso, a expressão regular linha, ou seja, listamos as linhas que musica:interprete~musica:...”
complexa (Linux | linux) usa os parênte- começam por um traço (-), seguido de
ses para agrupar as opções e a barra ver- qualquer coisa (o ponto), novamente Desta forma, musinc estará recebendo os
tical (|) é usada como um “ou” (or, em seguido de qualquer coisa, e por fim um dados de cada álbum como se fosse uma
inglês) lógico, isto é, estou procurando x ou um s. Obteríamos o mesmo resul- variável. A única diferença entre um
Linux ou linux. tado se usássemos o comando: parâmetro recebido e uma variável é que
No segundo, a expressão regular os primeiros recebem nomes numéricos
[Ll]inux significa: começado por L ou l $ ls -la | grep ‘^-..[xs]’ (o que quis dizer é que seus nomes são
seguido de inux. Como esta é uma formados somente por um algarismo,
expressão simples, o grep consegue e além disso, agilizaríamos a pesquisa. isto é, $1, $2, $3, …, $9). Vamos, fazer
resolvê-la, por isso é melhor usar a mais alguns testes:
segunda forma, já que o egrep tornaria a A “CDteca”
pesquisa mais lenta. Vamos começar a desenvolver progra- $ cat teste
Outro exemplo. Para listar todos os mas! Creio que a montagem de um #!/bin/bash
subdiretórios do diretório corrente, basta banco de dados de músicas é bacana #Teste de passagem de parametros
usar o comando $ ls -l | grep ‘^d’. Veja o para efeito didático (e útil nestes tempos echo “1o. parm -> $1”
resultado no Quadro 1. de downloads de arquivos MP3 e echo “2o. parm -> $2”
No exemplo, o circunflexo (^) serviu queimadores de CDs). Não se esqueça echo “3o. parm -> $3”
para limitar a pesquisa à primeira que, da mesma forma que vamos desen-
posição da saída do ls longo (parâmetro volver um monte de programas para Agora vamos rodar esse programinha:
organizar os seus CDs de música, com
Tabela 1 pequenas adaptações você pode fazer o $ teste passando parametros para U
mesmo para organizar os CDs de soft- testar
Posição Valores possíveis
1ª -
ware que vêm com a Linux Magazine e bash: teste: cannot execute
2ª r ou -
outros que você compra ou queima, e
3ª w ou - disponibilizar esse banco de software Ops! Esqueci-me de tornar o script exe-
4ª x,s(suid) ou - para todos os que trabalham com você cutável. Vou fazer isso e testar nova-
(o Linux é multiusuário, e como tal deve mente o programa:

88 Setembro 2004 [Link]


Papo de Botequim LINUX USER

$ chmod 755 teste Execute o programa: inclusão de CDs no meu banco chamado
$ teste passando parametros para U musicas. O programa é muito simples
testar $ teste passando parametros para testar (como tudo em Shell). Veja a Listagem 1.
1o. parm -> passando O programa teste recebeu 4 U O script é simples e funcional; limito-
2o. parm -> parametros parametros me a anexar ao fim do arquivo musicas o
3o. parm -> para 1o. parm -> passando parâmetro recebido. Vamos cadastrar 3
2o. parm -> parametros álbuns para ver se funciona (para não
Repare que a palavra testar, que seria o 3o. parm -> para ficar “enchendo lingüiça,” suponho que
quarto parâmetro, não foi listada. Isso Para listar todos de uma U em cada CD só existem duas músicas):
ocorreu porque o programa teste só lista “tacada” eu faco passando U
os três primeiros parâmetros recebidos. parametros para testar $ musinc “album3^Artista5U
Vamos executá-lo de outra forma: ~Musica5:Artista6~Musica5”
Repare que antes das aspas usei uma $ musinc “album1^Artista1U
$ teste “passando parametros” U barra invertida, para escondê-las da ~Musica1:Artista2~Musica2”
para testar interpretação do Shell (se não usasse as $ musinc “album 2^Artista3U
1o. parm -> passando parametros contrabarras as aspas não apareceriam). ~Musica3:Artista4~Musica4”
2o. parm -> para Como disse, os parâmetros recebem
3o. parm -> testar números de 1 a 9, mas isso não significa Listando o conteúdo do arquivo musicas:
que não posso usar mais de nove
As aspas não deixaram o Shell ver o parâmetros. Significa que só posso $ cat musicas
espaço em branco entre as duas endereçar nove. Vamos testar isso: album3^Artista5~Musica5:Artista6U
primeiras palavras, e elas foram consid- ~Musica6
eradas como um único parâmetro. E $ cat teste album1^Artista1~Musica1:Artista2U
falando em passagem de parâmetros, #!/bin/bash ~Musica2
uma dica: veja na Tabela 2 algumas var- # Programa para testar passagem U album2^Artista3~Musica3:Artista4U
iáveis especiais. Vamos alterar o pro- de parametros (3a. Versao) ~Musica4
grama teste para usar as novas variáveis: echo O programa $0 recebeu $# U
parametros Podia ter ficado melhor. Os álbuns estão
$ cat teste echo “11o. parm -> $11” fora de ordem, dificultando a pesquisa.
#!/bin/bash shift Vamos alterar nosso script e depois testá-
# Programa para testar passagem U echo “2o. parm -> $1” lo novamente. Veja a listagem 2. Sim-
de parametros (2a. Versao) shift 2 plesmente inseri uma linha que classifica
echo O programa $0 recebeu $# U echo “4o. parm -> $1” o arquivo musicas, redirecionando a
parametros saída para ele mesmo (para isso serve a
echo “1o. parm -> $1” Execute o programa: opção -o), após cada álbum ser anexado.
echo “2o. parm -> $2”
echo “3o. parm -> $3” $ teste passando parametros para U $ cat musicas
echo Para listar todos de uma U testar album1^Artista1~Musica1:Artista2U
\”tacada\” eu faco $* O programa teste recebeu 4 U ~Musica2
parametros que são: albu2^Artista3~Musica3:Artista4U
Listagem 1: Incluindo CDs 11o. parm -> passando1 ~Musica4
na “CDTeca” 2o. parm -> parametros album3^Artista5~Musica5:Artista6U
4o. parm -> testar ~Musica6
$ cat musinc
#!/bin/bash Duas coisas muito interessantes aconte- Oba! Agora o programa está legal e
# Cadastra CDs (versao 1) ceram neste script. Para mostrar que os quase funcional. Ficará muito melhor em
# nomes dos parâmetros variam de $1 a $9 uma nova versão, que desenvolveremos
echo $1 >> musicas digitei echo $11 e o que aconteceu? O após aprender a adquirir os dados da tela
Shell interpretou como sendo $1 seguido e formatar a entrada.
do algarismo 1 e listou passando1;
Listagem 2 O comando shift, cuja sintaxe é shift n, Tabela 2: Variáveis especiais
podendo o n assumir qualquer valor
$ cat musinc Variável Significado
numérico, despreza os n primeiros
#!/bin/bash $0 Contém o nome do programa
parâmetros, tornando o parâmetro de
# Cadastra CDs (versao 2) $# Contém a quantidade de
ordem n+1. parâmetros passados
#
Bem, agora que você já sabe sobre $* Contém o conjunto de todos os
echo $1 >> musicas
passagem de parâmetros, vamos voltar à parâmetros (muito parecido com $@)
sort -o musicas musicas
nossa “cdteca” para fazer o script de

[Link] Setembro 2004 89


LINUX USER Papo de Botequim

Ficar listando arquivos com o grep <cadeia de caracteres> U Listagem 5 - musexc


comando cat não está com nada, vamos [arq1, arq2, ..., arqn]
fazer um programa chamado muslist $ cat musexc
para listar um álbum, cujo nome será O grep entendeu que deveria procurar a #!/bin/bash
passado como parâmetro. Veja o código cadeia de caracteres album nos arquivos # Exclui CDs (versao 1)
na Listagem 3: 2 e musicas. Como o arquivo 2 não #
Vamos executá-lo, procurando pelo existe, grep gerou o erro e, por encontrar grep -v “$1” musicas > /tmp/mus$$
album 2. Como já vimos antes, para pas- a palavra album em todos os registros de mv -f /tmp/mus$$ musicas
sar a string album 2 é necessário pro- musicas, listou a todos.
tegê-la da interpretação do Shell, para É melhor ignorarmos maiúsculas e
que ele não a interprete como dois minúsculas na pesquisa. Resolveremos mando. Estamos então prontos para
parâmetros. Exemplo: os dois problemas com a Listagem 4. desenvolver o script para remover CDs
Nesse caso, usamos a opção -i do grep empenados da sua “CDteca”. Veja o
$ muslist “album 2” que, como já vimos, serve para ignorar código da Listagem 5.
grep: can’t open 2 maiúsculas e minúsculas, e colocamos o Na primeira linha mandei para
musicas: album1^Artista1~Musica1U $1 entre aspas, para que o grep continu- /tmp/mus$$ o arquivo musicas, sem os
:Artista2~Musica2 asse a ver a cadeia de caracteres resul- registros que atendessem a consulta feita
musicas: album2^Artista3~Musica3U tante da expansão da linha pelo Shell pelo comando grep. Em seguida, movi
:Artista4~Musica4 como um único argumento de pesquisa. /tmp/mus$$ por cima do antigo musicas.
musicas:album3^Artista5~Musica5U Usei o arquivo /tmp/mus$$ como arqui-
:Artista6~Musica6 $ muslist “album 2” vo de trabalho porque, como já havia
album2^Artista3~Musica3:Artista4U citado no artigo anterior, o $$ contém o
Que lambança! Onde está o erro? Eu tive ~Musica4 PID (identificação do processo) e, dessa
o cuidado de colocar o parâmetro pas- forma, cada um que editar o arquivo
sado entre aspas para o Shell não o Agora repare que o grep localiza a musicas o fará em um arquivo de tra-
dividir em dois! É, mas repare como o cadeia pesquisada em qualquer lugar do balho diferente, evitando colisões.
grep está sendo executado: registro; então, da forma que estamos Os programas que fizemos até aqui
fazendo, podemos pesquisar por álbum, ainda são muito simples, devido à falta
grep $1 musicas por música, por intérprete e mais. de ferramentas que ainda temos. Mas é
Quando conhecermos os comandos bom praticar os exemplos dados porque,
Mesmo colocando álbum 2 entre aspas, condicionais, montaremos uma nova eu prometo, chegaremos a desenvolver
para que fosse encarado como um único versão de muslist que permitirá especi- um sistema bacana para controle dos
parâmetro, quando o $1 foi passado pelo ficar por qual campo pesquisar. seus CDs. Na próxima vez que nos
Shell para o comando grep, transformou- Ah! Em um dia de verão você foi à encontrarmos, vou te ensinar como fun-
se em dois argumentos. Dessa forma, o praia, esqueceu os CDs no carro, aquele cionam os comandos condicionais e
conteúdo da linha que o grep executou “solzinho” de 40 graus empenou seu aprimoraremos mais um pouco esses
foi o seguinte: disco favorito e agora você precisa de scripts. Por hoje chega! Já falei demais e
uma ferramenta para removê-lo do estou de goela seca! Garçom! Mais um
grep album 2 musicas banco de dados? Não tem problema, sem colarinho! ■
vamos desenvolver um script chamado
Como a sintaxe do grep é: musexc, para excluir estes CDs. INFORMAÇÕES
Antes de desenvolver o “bacalho”,
Listagem 3 - muslist quero te apresentar a uma opção bas- [1] [Link]
tante útil da família de comandos grep. É ferramentas.php3
$ cat muslist
a opção -v, que quando usada lista todos [2] [Link]
#!/bin/bash
os registros da entrada, exceto o(s) local- ereg.php3
# Consulta CDs (versao 1)
izado(s) pelo comando. Exemplos: [3] [Link]
#
grep $1 musicas
$ grep -v “album 2” musicas
album1^Artista1~Musica1:Artista2U Julio Cezar Neves é
SOBRE O AUTOR

Analista de Suporte de
Listagem 4 ~Musica2
Sistemas desde 1969 e
muslist melhorado album3^Artista5~Musica5:Artista6U trabalha com Unix
~Musica6 desde 1980, quando
$ cat muslist
fez parte da equipe
#!/bin/bash
Conforme expliquei antes, o grep do que desenvolveu o
# Consulta CDs (versao 2) SOX, um sistema
exemplo listou todos os registros de
# operacional similar ao Unix, produzido
musicas exceto o referente a album 2, pela Cobra Computadores.
grep -i “$1” musicas
porque atendia ao argumento do co-

90 Setembro 2004 [Link]


����������������������������������������������������
�����������������������������������������������������������������������������������������������������������������������������������������������������
Papo฀de฀Botequim LINUX฀USER

Curso฀de฀Shell฀Script

Papo฀de฀
botequim฀III
Um฀chopinho,฀um฀aperitivo฀e฀o฀papo฀continua.฀Desta฀vez฀vamos฀aprender฀

alguns฀comandos฀de฀manipulação฀de฀cadeias฀de฀caracteres,฀que฀serão฀muito฀

úteis฀na฀hora฀de฀incrementar฀nossa฀“CDteca”.฀POR฀JULIO฀CEZAR฀NEVES฀

G arçon!฀ traga฀ dois฀ chopes฀ por฀


favor฀ que฀ hoje฀ eu฀ vou฀ ter฀ que฀
falar฀ muito.฀ Primeiro฀ quero฀
mostrar฀ uns฀ programinhas฀ simples฀
de฀usar฀e฀muito฀úteis,฀como฀o฀cut,฀que฀
Então,฀ recapitulando,฀ o฀ layout฀
do฀ arquivo฀ é฀ o฀ seguinte:฀ nome฀ do฀
álbum^intérprete1~nome฀da฀música1:...:
intérpreten~nome฀da฀músican,฀isto฀é,฀o฀
nome฀do฀álbum฀será฀separado฀por฀um฀
A
A
A
A
i
i
i
i
a
a4
a
a8

é฀ usado฀ para฀ cortar฀ um฀ determinado฀ circunfl฀exo฀(^)฀do฀resto฀do฀registro,฀que฀ Para฀entender฀melhor฀isso,฀vamos฀anali-


pedaço฀ de฀ um฀ arquivo.฀ A฀ sintaxe฀ e฀ é฀formado฀por฀diversos฀grupos฀compos- sar฀a฀primeira฀linha฀de฀musicas:
alguns฀exemplos฀de฀uso฀podem฀ser฀vis- tos฀ pelo฀ intérprete฀ de฀ cada฀ música฀ do฀
tos฀no฀Quadro฀1: CD฀e฀a฀respectiva฀música฀interpretada.฀ $ head - ica
Como฀ dá฀ para฀ ver,฀ existem฀ quatro฀ Estes฀grupos฀são฀separados฀entre฀si฀por฀ alb ^A i a ~M ica : U
sintaxes฀distintas:฀na฀primeira฀(-c฀1-5)฀ dois-pontos฀(:)฀e฀o฀intérprete฀será฀sepa- A i a ~M ica
especifiquei฀ uma฀ faixa,฀ na฀ segunda rado฀do฀nome฀da฀música฀por฀um฀til฀(~).
(-c฀ -6)฀ especifiquei฀ todo฀ o฀ texto฀ até฀ Então,฀para฀pegar฀os฀dados฀referentes฀ Então฀observe฀o฀que฀foi฀feito:
uma฀posição,฀na฀terceira฀(-c฀4-)฀tudo฀de฀ a฀todas฀as฀segundas฀músicas฀do฀arquivo฀
uma฀determinada฀posição฀em฀diante฀e฀ musicas,฀devemos฀digitar: alb ^A i a ~M ica : U
na฀quarta฀(-c฀1,3,5,7,9),฀só฀as฀posições฀ A i a ~M ica
determinadas.฀ A฀ última฀ possibilidade฀ $ c -f -d: ica
(-c฀-3,5,8-)฀foi฀só฀para฀mostrar฀que฀pode- A i a ~M ica Desta฀forma,฀no฀primeiro฀cut฀o฀primeiro฀
mos฀misturar฀tudo. A i a4~M ica4 campo฀ do฀ delimitador฀ (-d)฀ dois-pon-
Mas฀ não฀ pense฀ que฀ acabou฀ por฀ aí!฀ A i a ~M ica5 tos฀(:)฀é฀album฀1^Artista1~Musica1฀e฀o฀
Como฀ você฀ deve฀ ter฀ percebido,฀ esta฀ A i a8~M ica8@ L: segundo,฀ que฀ é฀ o฀ que฀ nos฀ interessa,฀ é฀
forma฀de฀cut฀é฀muito฀útil฀para฀lidar฀com฀ Artista2~Musica2.฀ Vamos฀ então฀ ver฀ o฀
arquivos฀com฀campos฀de฀tamanho฀fi฀xo,฀ Ou฀ seja,฀ cortamos฀ o฀ segundo฀ campo que฀aconteceu฀no฀segundo฀cut:
mas฀atualmente฀o฀que฀mais฀existe฀são฀ z(-f฀de฀fi฀eld,฀campo฀em฀inglês)฀delimi-
arquivos฀com฀campos฀de฀tamanho฀vari- tado฀ (-d)฀ por฀ dois-pontos฀ (:).฀ Mas,฀ se฀ A i a ~M ica
ável,฀onde฀cada฀campo฀termina฀com฀um฀ quisermos฀somente฀os฀intérpretes,฀deve-
delimitador.฀Vamos฀dar฀uma฀olhada฀no฀ mos฀digitar: Agora,฀primeiro฀campo฀do฀delimitador฀
arquivo฀musicas฀que฀começamos฀a฀pre- (-d)฀til฀(~),฀que฀é฀o฀que฀nos฀interessa,฀
parar฀na฀última฀vez฀que฀viemos฀aqui฀no฀ $ c -f -d: ica | c U é฀ Artista2฀ e฀ o฀ segundo฀ é฀ Musica2.฀ Se฀
botequim.฀Veja฀o฀Quadro฀2. -f -d~ o฀ raciocínio฀ que฀ fizemos฀ para฀ a฀ pri-

�����������������������������
[Link]฀ Outubro฀2004 85
��������������������������������������������������������������������������������
���������������������������������������������������
����������������������������������������������������������������������������������������������������������������������������������������������������
LINUX฀USER Papo฀de฀Botequim

Quadro฀1฀–฀O฀comando฀cut meira฀linha฀for฀aplicado฀ao฀restante฀do฀
arquivo,฀ chegaremos฀ à฀ resposta฀ ante-
posta฀ a฀ um฀ exercício฀ prático,฀ valendo฀
nota,฀ que฀ passei฀ ele฀ me฀ entregou฀ um฀
riormente฀dada.฀Outro฀comando฀muito฀ script฀ com฀ todos฀ os฀ comandos฀ sepa-
A฀sintaxe฀do฀cut฀é:฀cut฀-c฀PosIni-PosFim฀
interessante฀é฀o฀tr฀que฀serve฀para฀subs- rados฀ por฀ ponto-e-vírgula฀ (lembre-se฀
[arquivo],฀onde฀PosIni฀é฀a฀posição฀inicial,฀e฀
tituir,฀comprimir฀ou฀remover฀caracteres.฀ que฀o฀ponto-e-vírgula฀serve฀para฀sepa-
PosFim฀a฀posição฀fi฀nal.฀Veja฀os฀exemplos:
Sua฀sintaxe฀segue฀o฀seguinte฀padrão: rar฀diversos฀comandos฀em฀uma฀mesma฀
linha).฀ Vou฀ dar฀ um฀ exemplo฀ simplifi฀-
$ ca e
[ ç e ] cadeia [cadeia ] cado,฀e฀idiota,฀de฀um฀script฀assim:
45 8
8 54
O฀ comando฀ copia฀ o฀ texto฀ da฀ entrada฀ $ ca c f
4554
padrão฀(stdin),฀troca฀as฀ocorrência฀dos฀ ech leia P g a açã Shell U
8 55 8
caracteres฀ de฀ cadeia1฀ pelo฀ seu฀ corres- Li d J li Ce a Ne e U
pondente฀na฀cadeia2฀ou฀troca฀múltiplas฀ > li ca li d l U
$ c -c -5 e
ocorrências฀ dos฀ caracteres฀ de฀ cadeia1฀ -f li > de ll cd ~
45
por฀ somente฀ um฀ caracter,฀ ou฀ ainda฀
8
caracteres฀ da฀ cadeia1.฀ As฀ principais฀ Eu฀executei฀o฀programa฀e฀ele฀funcionou:
45
opções฀ do฀ comando฀ são฀ mostradas฀ na฀
8 5
Tabela฀1. $ c f
Primeiro฀veja฀um฀exemplo฀bem฀bobo: leia P g a açã Shell Li U
$ c -c- e
d J li Ce a Ne e
45
$ ech b b | a h e j e e LM
85
baba c f li e c ica
455
i c li e
8 55
Isto฀é,฀troquei฀todas฀as฀ocorrências฀da฀
letra฀ o฀ pela฀ letra฀ a.฀ Suponha฀ que฀ em฀ Mas฀nota฀de฀prova฀é฀coisa฀séria฀(e฀nota฀
$ c -c4- e
determinado฀ ponto฀ do฀ meu฀ script฀ eu฀ de฀ dólar฀ é฀ mais฀ ainda)฀ então,฀ para฀
45 8
peça฀ ao฀ operador฀ para฀ digitar฀ s฀ ou฀ n฀ entender฀ o฀ que฀ o฀ aluno฀ havia฀ feito,฀ o฀
54
(sim฀ ou฀ não),฀ e฀ guardo฀ sua฀ resposta฀ chamei฀e฀em฀sua฀frente฀digitei:
4554
na฀ variável฀ $Resp.฀ Ora,฀ o฀ conteúdo฀ de฀
55 8
$Resp฀ pode฀ conter฀ letras฀ maiúsculas฀ $ \ < c f
ou฀minúsculas,฀e฀desta฀forma฀eu฀teria฀ ech leia P g a açã Shell U
$ c -c , ,5, , e
que฀fazer฀diversos฀testes฀para฀saber฀se฀ Li d J li Ce a Ne e
5
a฀resposta฀dada฀foi฀S,฀s,฀N฀ou฀n.฀Então฀o฀ d
8 4
melhor฀é฀fazer: cd ~
54
l -l
5 8
$ Re =$ ech $Re | SN -f li > de ll

$ c -c - ,5,8- e
e฀ após฀ este฀ comando฀ eu฀ teria฀ certeza฀ O฀cara฀fi฀cou฀muito฀desapontado,฀porque฀
58
de฀ que฀ o฀ conteúdo฀ de฀ $Resp฀ seria฀ um฀ em฀ dois฀ ou฀ três฀ segundos฀ eu฀ desfi฀z฀ a฀
8
s฀ ou฀ um฀ n.฀ Se฀ o฀ meu฀ arquivo฀ ArqEnt฀ gozação฀que฀ele฀perdeu฀horas฀para฀fazer.฀
5
está฀todo฀em฀letras฀maiúsculas฀e฀desejo฀ Mas฀preste฀atenção!฀Se฀eu฀estivesse฀em฀
8 5 8
passá-las฀para฀minúsculas฀eu฀faço: uma฀máquina฀Unix,฀eu฀teria฀digitado:

$ A-Z a- < A E > $$ $ \ < c f


Quadro฀2฀–฀O฀arquivo฀ $ -f $$ A E
musicas Agora฀veja฀a฀diferença฀entre฀o฀resultado฀
Note฀ que฀ neste฀ caso฀ usei฀ a฀ notação฀ A- de฀um฀comando฀date฀executado฀hoje฀e฀
Z฀para฀não฀escrever฀ABCD…YZ.฀Outro฀ outro฀executado฀há฀duas฀semanas:
$ ca ica
tipo฀de฀notação฀que฀pode฀ser฀usada฀são฀
alb ^A i a ~M ica :U
as฀ escape฀ sequences฀ (como฀ eu฀ traduzi- S Se 4:5 :54 4
A i a ~M ica
ria?฀ Seqüências฀ de฀ escape?฀ Meio฀ sem฀ S Se 5 : : 4
alb ^A i a ~M ica :U
sentido,฀né?฀Mas฀vá฀lá…)฀que฀também฀
A i a4~M ica4
são฀reconhecidas฀por฀outros฀comandos฀ Notou฀o฀espaço฀extra฀após฀o฀“Sep”฀na฀
alb ^A i a5~M ica5:U
e฀também฀na฀linguagem฀C,฀e฀cujo฀signi- segunda฀ linha?฀ Para฀ pegar฀ a฀ hora฀ eu฀
A i a ~M ica5
fi฀cado฀você฀verá฀na฀Tabela฀2: deveria฀digitar:
alb 4^A i a ~M ica :U
Deixa฀ eu฀ te฀ contar฀ um฀ “causo”:฀ um฀
A i a8~M ica8
aluno฀que฀estava฀danado฀comigo฀resol- $ da e | c -f 4 -d
veu฀complicar฀minha฀vida฀e฀como฀res- 4:5 :54

�����������������������������
86 Outubro฀2004 [Link]฀
��������������������������������������������������������������������������������
����������������������������������������������������
�����������������������������������������������������������������������������������������������������������������������������������������������������
Papo฀de฀Botequim LINUX฀USER

Mas฀ há฀ duas฀ semanas฀ ocorreria฀ o฀ Bem฀a฀opção฀-d฀do฀tr฀remove฀do฀arquivo฀ E฀veja฀também฀o฀date:


seguinte: todas฀as฀ocorrências฀do฀caractere฀espe-
cificado.฀ Desta฀ forma฀ eu฀ removi฀ os฀ $ da e
$ da e | c -f 4 -d caracteres฀ indesejados,฀ salvei฀ o฀ texto฀ M Se :4 : BRT 4
5 em฀um฀arquivo฀temporário฀e฀posterior-
mente฀renomeei-o฀para฀o฀nome฀original.฀ Repare฀ que฀ o฀ mês฀ e฀ o฀ dia฀ estão฀ no฀
Isto฀ porque฀ existem฀ 2฀ caracteres฀ em฀ Uma฀observação:฀em฀um฀sistema฀Unix฀ mesmo฀ formato฀ em฀ ambos฀ os฀ coman-
branco฀antes฀do฀5฀(dia).฀Então฀o฀ideal฀ eu฀deveria฀digitar: dos.฀Ora,฀se฀em฀algum฀registro฀do฀who฀
seria฀transformar฀os฀espaços฀em฀branco฀ eu฀não฀encontrar฀a฀data฀de฀hoje,฀é฀sinal฀
consecutivos฀ em฀ somente฀ um฀ espaço฀ $ -d \ 5 < A D DOS U que฀ o฀ usuário฀ está฀ “logado”฀ há฀ mais฀
para฀poder฀tratar฀os฀dois฀resultados฀do฀ > $$ de฀ um฀ dia,฀ já฀ que฀ ele฀ não฀ pode฀ ter฀ se฀
comando฀date฀da฀mesma฀forma,฀e฀isso฀ “logado”฀ amanhã…฀ Então฀ vamos฀ guar-
se฀faz฀assim: Uma฀dica:฀o฀problema฀com฀os฀termina- dar฀ o฀ pedaço฀ que฀ importa฀ da฀ data฀ de฀
dores฀ de฀ linha฀ (CR/LF)฀ só฀ aconteceu฀ hoje฀para฀depois฀procurá-la฀na฀saída฀do฀
$ da e | - porque฀ a฀ transferência฀ do฀ arquivo฀ foi฀ comando฀who:
S Se 5 : : 4 feita฀ no฀ modo฀ binário฀ (ou฀ image),฀ Se฀
antes฀da฀transmissão฀do฀arquivo฀tivesse฀ $ Da a=$ da e | c -f - U
E฀agora฀eu฀posso฀cortar: sido฀estipulada฀a฀opção฀ascii฀do฀ftp,฀isto฀ -d
não฀teria฀ocorrido.
$ da e | - | c -f 4 U –฀Olha,฀depois฀desta฀dica฀tô฀começando฀a฀ Eu฀ usei฀ a฀ construção฀ $(...),฀ para฀ prio-
-d gostar฀deste฀tal฀de฀shell,฀mas฀ainda฀tem฀ rizar฀ a฀ execução฀ dos฀ comandos฀ antes฀
: : muita฀coisa฀que฀não฀consigo฀fazer. de฀atribuir฀a฀sua฀saída฀à฀variável฀Data.฀
–฀฀Pois฀é,฀ainda฀não฀te฀falei฀quase฀nada฀ Vamos฀ver฀se฀funcionou:
Olha฀só฀como฀o฀Shell฀está฀quebrando฀o฀ sobre฀ programação฀ em฀ shell,฀ ainda฀
galho.฀Veja฀o฀conteúdo฀de฀um฀arquivo฀ tem฀ muita฀ coisa฀ para฀ aprender,฀ mas฀ $ ech $Da a
baixado฀de฀uma฀máquina฀Windows: com฀o฀que฀aprendeu,฀já฀dá฀para฀resol- Se
ver฀muitos฀problemas,฀desde฀que฀você฀
$ ca - e A D DOS adquira฀o฀“modo฀shell฀de฀pensar”.฀Você฀ Beleza!฀Agora,฀o฀que฀temos฀que฀fazer฀é฀
E e a i ^M$ seria฀capaz฀de฀fazer฀um฀script฀que฀diga฀ procurar฀no฀comando฀who฀os฀registros฀
f i ge ad el ^M$ quais฀pessoas฀estão฀“logadas”฀há฀mais฀ que฀não฀possuem฀esta฀data.
DOS Wi e f i^M$ de฀um฀dia฀no฀seu฀servidor?
bai ad ^M$ –฀฀Claro฀que฀não!฀Para฀isso฀seria฀necessá- –฀฀A h!฀ Eu฀ acho฀ que฀ estou฀ entendendo!฀
f al fei ^M$ rio฀eu฀conhecer฀os฀comandos฀condicio- Você฀falou฀em฀procurar฀e฀me฀ocorreu฀o฀
nais฀que฀você฀ainda฀não฀me฀explicou฀ comando฀grep,฀estou฀certo?
Dica:฀a฀opção฀-v฀do฀cat฀mostra฀os฀carac- como฀ funcionam.฀ -฀ Deixa฀ eu฀ tentar฀ –฀฀Certíssimo!฀Só฀que฀eu฀tenho฀que฀usar฀o฀
teres฀de฀controle฀invisíveis,฀com฀a฀nota- mudar฀um฀pouco฀a฀sua฀lógica฀e฀trazê- grep฀com฀aquela฀opção฀que฀ele฀só฀lista฀
ção฀ ^L,฀ onde฀ ^฀ é฀ a฀ tecla฀ Control฀ e฀ L฀ é฀ la฀para฀o฀“modo฀shell฀de฀pensar”,฀mas฀ os฀ registros฀ nos฀ quais฀ ele฀ não฀ encon-
a฀respectiva฀letra.฀A฀opção฀-e฀mostra฀o฀ antes฀é฀melhor฀tomarmos฀um฀chope. trou฀ a฀ cadeia.฀ Você฀ se฀ lembra฀ que฀
fi฀nal฀da฀linha฀como฀um฀cifrão฀($). Agora฀que฀já฀molhei฀a฀palavra,฀vamos฀ opção฀é฀essa?
Isto฀ocorre฀porque฀no฀DOS฀o฀fi฀m฀dos฀ resolver฀o฀problema฀que฀te฀propus.฀Veja฀ –฀฀Claro,฀a฀-v…
registros฀ é฀ indicado฀ por฀ um฀ Carriage฀ como฀funciona฀o฀comando฀who: –฀฀Isso!฀Tá฀fi฀cando฀bom!฀Vamos฀ver:
Return฀ (\r฀ –฀ Retorno฀ de฀ Carro,฀ CR)฀ e฀
um฀Line฀Feed฀(\f฀–฀Avanço฀de฀Linha,฀ou฀ $ h $ h | g e - $Da a
LF).฀ No฀ Linux฀ porém฀ o฀ fi฀nal฀ do฀ regis- j e e U j e e U
tro฀é฀indicado฀somente฀pelo฀Line฀Feed.฀ Se 8 :4 Se 8 :4
Vamos฀limpar฀este฀arquivo: e U
Se : Se฀eu฀quisesse฀um฀pouco฀mais฀de฀perfu-
$ -d \ < A D DOS > $$ lega ia U maria฀eu฀faria฀assim:
$ -f $$ A D DOS Se 8:
lca l U $ h | g e - $Da a |U
Agora฀vamos฀ver฀o฀que฀aconteceu: Se : c -f -d
j e e
$ ca - e A D DOS Tabela฀1฀–฀O฀comando฀tr
E e a i $ Opção฀ Signifi฀cado Viu?฀Não฀foi฀necessário฀usar฀comando฀
f i ge ad el $ condicional,฀ até฀ porque฀ o฀ nosso฀
-s฀ Comprime฀n฀ocorrências฀de
DOS R i e f i$ ฀ cadeia1฀em฀apenas฀uma
comando฀condicional,฀o฀famoso฀if,฀não฀
bai ad $ testa฀ condição,฀ mas฀ sim฀ instruções.฀
-d฀ Remove฀os฀caracteres฀de฀cadeia1
f al fei $ Mas฀antes฀veja฀isso:

�����������������������������
[Link]฀ Outubro฀2004 87
��������������������������������������������������������������������������������
���������������������������������������������������
����������������������������������������������������������������������������������������������������������������������������������������������������
LINUX฀USER Papo฀de฀Botequim

$ l ica Tabela฀2 de ll
ica Seqüência Signifi฀cado Octal he
$ ech $ \t Tabulação \011 ech U a i \ $ \ já U
\n Nova฀linha฀ \012 e i e
$ l A I e i e e <ENTER> el e
l : A I e i e e: N ch฀U \v Tabulação฀ \013 if e add $
file di ec Vertical he
$ ech $ \f Nova฀ \014 ech U á i \ $ \ U
Página i cl íd e e c a d
$ h | g e j e e \r Início฀da฀ \015 el e
j e e Se 8 U linha฀<^M> ech P ble a U
\\ Uma฀barra฀ \0134
:4 4 44 cada a e V cê é
invertida
$ ech $ fi

$ h | g e j lia a ฀ já e i e
$ ech $ el e Vamos฀testá-lo฀como฀um฀usuário฀normal฀:
if e add $
he $ i c ZeNi g e
O฀que฀é฀que฀esse฀$?฀faz฀aí?฀Algo฀come- ech U á i \ $ \ U i c [ ]: e add: f d
çado฀por฀cifrão฀($)฀parece฀ser฀uma฀vari- i cl íd e e c a d P ble a cada a e U
ável,฀ certo?฀ Sim฀ é฀ uma฀ variável฀ que฀ el e V cê é
contém฀o฀código฀de฀retorno฀da฀última฀ ech P ble a U
instrução฀ executada.฀ Posso฀ te฀ garan- cada a e V cê é Aquela฀mensagem฀de฀erro฀não฀deveria฀
tir฀que฀se฀esta฀instrução฀foi฀bem฀suce- fi aparecer!฀ Para฀ evitar฀ isso,฀ devemos฀
dida,฀$?฀terá฀o฀valor฀zero,฀caso฀contrário฀ fi redirecionar฀a฀saída฀de฀erro฀(stderr)฀do฀
seu฀valor฀será฀diferente฀de฀zero.฀O฀que฀ comando฀useradd฀para฀/dev/null.฀A฀ver-
nosso฀ comando฀ condicional฀ (if)฀ faz฀ é฀ Repare฀ que฀ o฀ if฀ está฀ testando฀ direto฀ o฀ são฀fi฀nal฀fi฀ca฀assim:
testar฀esta฀variável.฀Então฀vamos฀ver฀a฀ comando฀grep฀e฀esta฀é฀a฀sua฀fi฀nalidade.฀
sua฀sintaxe: Caso฀o฀if฀seja฀bem฀sucedido,฀ou฀seja,฀o฀ $ ca i c
usuário฀ (cujo฀ nome฀ está฀ em฀ $1)฀ foi฀ ! bi ba h
if c d encontrado฀em฀/etc/passwd,฀os฀coman- Ve ã
he dos฀do฀bloco฀do฀then฀serão฀executados฀ if g e ^$ e c a d > U
c d (neste฀ exemplo,฀ apenas฀ o฀ echo).฀ Caso฀ de ll
c d contrário,฀as฀instruções฀do฀bloco฀do฀else฀ he
c d serão฀ executadas,฀ quando฀ um฀ novo฀ if฀ ech U a i \ $ \ já U
el e testa฀ se฀ o฀ comando฀ useradd฀ foi฀ execu- e i e
c d tado฀a฀contento,฀criando฀o฀registro฀do฀ el e
c d4 usuário฀ em฀ /etc/passwd,฀ ou฀ exibindo฀ if e add $ > de ll
c d uma฀mensagem฀de฀erro,฀caso฀contrário. he
fi Executar฀ o฀ programa฀ e฀ passe฀ como฀ ech U á i \ $ \ U
parâmetro฀um฀usuário฀já฀cadastrado: i cl íd e e c a d
Ou฀seja,฀caso฀comando฀cmd฀tenha฀sido฀ el e
executado฀ com฀ sucesso,฀ os฀ comandos฀ $ i c j e e ech P ble a U
do฀bloco฀do฀then฀(cmd1,฀cmd2฀e฀cmdn)฀ j e e : :54 : :J li Ne e : U cada a e V cê é
serão฀ executados,฀ caso฀ contrário,฀ os฀ h e j e e : bi U fi
comandos฀ do฀ bloco฀ opcional฀ do฀ else฀ ba h fi
(cmd3,฀cmd4฀e฀cmdm)฀serão฀executados.฀ U a i j e e ja e i e
O฀bloco฀do฀if฀é฀terminando฀com฀um฀fi฀. Depois฀disso,฀vejamos฀o฀comportamento฀
Vamos฀ver฀na฀prática฀como฀isso฀fun- No฀ exemplo฀ dado,฀ surgiu฀ uma฀ linha฀ do฀programa,฀se฀executado฀pelo฀root:
ciona,฀usando฀um฀script฀que฀inclui฀usu- indesejada,฀ ela฀ é฀ a฀ saída฀ do฀ comando฀
ários฀no฀arquivo฀/etc/passwd: grep.฀ Para฀ evitar฀ que฀ isso฀ aconteça,฀ $ i c b elh
devemos฀desviar฀a฀saída฀para฀/dev/null.฀ U á i b elh i cl id e U
$ ca i c O฀programa฀fi฀ca฀assim: e c a d
! bi ba h
Ve ã $ ca i c E฀novamente:
if g e ^$ e c a d ! bi ba h
he Ve ã $ i c b elh
ech U a i \ $ \ U if g e ^$ e c a d > U U á i b elh já e i e

�����������������������������
88 Outubro฀2004 [Link]฀
��������������������������������������������������������������������������������
����������������������������������������������������
�����������������������������������������������������������������������������������������������������������������������������������������������������
Papo฀de฀Botequim LINUX฀USER

Lembra฀ que฀ eu฀ falei฀ que฀ ao฀ longo฀ dos฀ no฀início฀da฀cadeia฀e฀cifrão฀($)฀no฀fi฀m,฀ Como฀ você฀ viu,฀ o฀ programa฀ melho-
nossos฀ papos฀ e฀ chopes฀ os฀ nossos฀ pro- servem฀ para฀ testar฀ se฀ o฀ parâmetro฀ (o฀ rou฀um฀pouquinho,฀mas฀ainda฀não฀está฀
gramas฀ iriam฀ se฀ aprimorando?฀ Então฀ álbum฀e฀seus฀dados)฀é฀exatamente฀igual฀ pronto.฀ À฀ medida฀ que฀ eu฀ te฀ ensinar฀ a฀
vejamos฀agora฀como฀podemos฀melhorar฀ a฀ algum฀ registro฀ já฀ existente.฀ Vamos฀ programar฀em฀shell,฀nossa฀CDteca฀vai฀
o฀nosso฀programa฀para฀incluir฀músicas฀ executar฀ nosso฀ programa฀ novamente,฀ fi฀car฀cada฀vez฀melhor.
na฀"CDTeca": mas฀desta฀vez฀passamos฀como฀parâme- –฀฀E ntendi฀ tudo฀ que฀ você฀ me฀ explicou,฀
tro฀um฀álbum฀já฀cadastrado,฀pra฀ver฀o฀ mas฀ ainda฀ não฀ sei฀ como฀ fazer฀ um฀ if฀
$ ca i c que฀acontece: para฀ testar฀ condições,฀ ou฀ seja฀ o฀ uso฀
! bi ba h normal฀do฀comando.
Cada a CD e a $ i c alb 4^A i a ~ U –฀฀Para฀ isso฀ existe฀ o฀ comando฀ test,฀ que฀
M ica :A i a8~M ica8 testa฀ condições.฀ O฀ comando฀ if฀ testa฀
if g e ^$ $ ica > U E e álb já e á cada ad o฀ comando฀ test.฀ Como฀ já฀ falei฀ muito,฀
de ll preciso฀de฀uns฀chopes฀para฀molhar฀a฀
he E฀agora฀um฀não฀cadastrado: palavra.฀ Vamos฀ parar฀ por฀ aqui฀ e฀ na฀
ech E e álb já e á U próxima฀ vez฀ te฀ explico฀ direitinho฀ o฀
cada ad $ i c alb 5^A i a ~ U uso฀do฀test฀e฀de฀diversas฀outras฀sinta-
el e M ica :A i a ~M ica xes฀do฀if.
ech $ >> ica $ ca ica –฀฀Falou!฀ Acho฀ bom฀ mesmo฀ porque฀ eu฀
ica - ica alb ^A i a ~M ica : U também฀ já฀ tô฀ fi฀cando฀ zonzo฀ e฀ assim฀
fi A i a ~M ica tenho฀tempo฀para฀praticar฀esse฀monte฀
alb ^A i a ~M ica : U de฀coisas฀que฀você฀me฀falou฀hoje.
Como฀você฀viu,฀é฀uma฀pequena฀evolu- A i a4~M ica4 Para฀fi฀xar฀o฀que฀você฀aprendeu,฀tente฀
ção฀em฀relação฀à฀versão฀anterior.฀Antes฀ alb ^A i a5~M ica5: U fazer฀um฀scriptizinho฀para฀informar฀se฀
de฀ incluir฀ um฀ registro฀ (que฀ na฀ versão฀ A i a ~M ica5 um฀ determinado฀ usuário,฀ cujo฀ nome฀
anterior฀ poderia฀ ser฀ duplicado),฀ testa- alb 4^A i a ~M ica : U será฀ passado฀ como฀ parâmetro,฀ está฀
mos฀se฀o฀registro฀começa฀(^)฀e฀termina฀ A i a8~M ica8 “logado”฀no฀sistema฀ou฀não.
($)฀ de฀ forma฀ idêntica฀ ao฀ parâmetro฀ alb 5^A i a ~M ica : U –฀฀Aê฀ Chico!฀ traz฀ mais฀ dois฀ chopes฀ pra฀
álbum฀ passado฀ ($1).฀ O฀ circunfl฀exo฀ (^)฀ A i a ~M ica mim฀por฀favor…฀ ■

�����������������������������
[Link]฀ Outubro฀2004 89
��������������������������������������������������������������������������������
���������������������������������������������������
����������������������������������������������������������������������������������������������������������������������������������������������������
LINUX฀USER Papo฀de฀Botequim

Curso฀de฀Shell฀Script

Papo฀de฀
botequim฀IV฀
O฀garçon฀já฀perdeu฀a฀conta฀das฀cervejas,฀e฀o฀assunto฀não฀acaba.฀Desta฀
Dave฀Hamilton฀-฀[Link]

vez฀vamos฀aprender฀a฀testar฀os฀mais฀variados฀tipos฀de฀condições,฀

para฀podermos฀controlar฀a฀execução฀de฀nosso฀programa฀de฀acordo฀

com฀a฀entrada฀fornecida฀pelo฀usuário.฀POR฀JULIO฀CEZAR฀NEVES

E฀ aí฀cara,฀tentou฀fazer฀o฀exercício฀
que฀ te฀ pedi฀ em฀ nosso฀ último฀
encontro?
–฀ Claro฀ que฀ sim!฀ Em฀ programação,฀ se฀
você฀ não฀ treinar฀ não฀ aprende.฀ Você฀
$ l gad j e e
j e e
: 4 44
j e e e á l gad
Oc 8 U
Ah,฀agora฀sim!฀Lembre-se฀dessa฀pega-
dinha:฀a฀maior฀parte฀dos฀comandos฀tem฀
uma฀saída฀padrão฀e฀uma฀saída฀de฀erros฀
(o฀ grep฀ é฀ uma฀ das฀ poucas฀ exceções:฀
ele฀ não฀ exibe฀ uma฀ mensagem฀ de฀ erro฀
me฀pediu฀um฀script฀para฀informar฀se฀ Realmente฀ funcionou.฀ Passei฀ meu฀ quando฀não฀acha฀uma฀cadeia฀de฀carac-
um฀determinado฀usuário,฀cujo฀nome฀ nome฀ de฀ usuário฀ como฀ parâmetro฀ e฀ teres)฀e฀devemos฀redirecioná-las฀para฀o฀
será฀passado฀como฀parâmetro฀para฀o฀ ele฀disse฀que฀eu฀estava฀logado,฀porém฀ buraco฀negro฀quando฀necessário.
script,฀está฀“logado”฀(arghh!)฀ou฀não.฀ ele฀ imprimiu฀ uma฀ linha฀ extra,฀ que฀ eu฀ Bem,฀agora฀vamos฀mudar฀de฀assunto:฀
Fiz฀o฀seguinte: não฀ pedi,฀ que฀ é฀ a฀ saída฀ do฀ comando฀ na฀ última฀ vez฀ que฀ nos฀ encontramos฀
who.฀ Para฀ evitar฀ que฀ isso฀ aconteça,฀ é฀ aqui฀no฀botequim,฀quando฀já฀estávamos฀
$ ca l gad só฀ mandá-la฀ para฀ o฀ buraco฀ negro฀ do฀ de฀goela฀seca,฀você฀me฀perguntou฀como฀
mundo฀ UNIX,฀ o฀ /dev/null.฀ Vejamos฀ se฀testam฀condições.฀Para฀isso,฀usamos฀
! bi ba h então฀como฀fi฀caria: o฀comando฀test
Pe i a e á i e á
l gad ã $ ca l gad Testes
! bi ba h Todos฀ estamos฀ acostumados฀ a฀ usar฀ o฀
if h | g e $ Pe i a e a e a e á if฀ para฀ testar฀ condições,฀ e฀ estas฀ são฀
he l gada ã e ã sempre฀ maior฀ que,฀ menor฀ que,฀ maior฀
ech $ e á l gad if h | g e $ > de ll ou฀igual฀a,฀menor฀ou฀igual฀a,฀igual฀a฀e฀
el e he
ech $ ã e á edaç ech $ e á l gad Tabela฀1฀–฀Opções฀do
fi el e test฀para฀arquivos
ech $ ã e á edaç Opção Verdadeiro฀se
–฀ Calma฀ rapaz!฀ Já฀ vi฀ que฀ você฀ chegou฀ fi -e฀arq arq฀existe
cheio฀de฀tesão.฀Primeiro฀vamos฀pedir฀ -s฀arq arq฀existe฀e฀tem฀tamanho฀maior฀que฀zero
os฀ nossos฀ chopes฀ de฀ praxe฀ e฀ depois฀ Agora฀vamos฀aos฀testes:
vamos฀ao฀Shell.฀Chico,฀traz฀dois฀cho- -f฀arq arq฀existe฀e฀é฀um฀arquivo฀regular
pes,฀um฀sem฀colarinho! $ l gad j e e -d฀arq arq฀existe฀e฀é฀um฀diretório
-r฀arq arq฀existe฀e฀com฀direito฀de฀leitura
–฀ Aaah!฀Agora฀que฀já฀molhamos฀os฀nos- j e e e á l gad
-w฀arq arq฀existe฀e฀com฀direito฀de฀escrita
sos฀bicos,฀vamos฀dar฀uma฀olhada฀nos฀ $ l gad chic
-x฀arq arq฀existe฀e฀com฀direito฀de฀execução
resultados฀do฀seu฀programa: chic ã e á edaç

�����������������������������
84 edição฀04 [Link]฀
��������������������������������������������������������������������������������
����������������������������������������������������
�����������������������������������������������������������������������������������������������������������������������������������������������������
Papo฀de฀Botequim LINUX฀USER

Tabela฀2฀–฀Opções฀do฀test฀ No฀ exemplo,฀ testei฀ a฀ existência฀ do฀ cadeia฀ de฀ caracteres฀ “01”฀ é฀ realmente฀
para฀cadeias฀de฀caracteres diretório฀lmb.฀Se฀não฀existisse฀(else),฀ele฀ diferente฀ de฀ “1”.฀ Porém,฀ a฀ coisa฀ muda฀
seria฀criado.฀Já฀sei,฀você฀vai฀criticar฀a฀ de฀fi฀gura฀quando฀as฀variáveis฀são฀testa-
Opção Verdadeiro฀se:
minha฀lógica฀dizendo฀que฀o฀script฀não฀ das฀numericamente,฀já฀que฀o฀número฀1฀
-z฀cadeia Tamanho฀de฀cadeia฀é฀zero
está฀otimizado.฀Eu฀sei,฀mas฀queria฀que฀ é฀igual฀ao฀número฀01.
-n฀cadeia Tamanho฀de฀cadeia฀é฀maior฀que฀zero
cadeia A฀cadeia฀cadeia฀tem฀tamanho฀maior฀que฀zero você฀ o฀ entendesse฀ assim,฀ para฀ então฀ Para฀mostrar฀o฀uso฀dos฀conectores฀-o฀
c1฀=฀c2 Cadeia฀c1฀e฀c2฀são฀idênticas poder฀usar฀o฀“ponto-de-espantação”฀(!)฀ (ou)฀e฀-a฀(e),฀veja฀um฀exemplo฀“animal”,฀
como฀um฀negador฀do฀test.฀Veja฀só: programado฀direto฀no฀prompt฀do฀Bash.฀
Me฀ desculpem฀ os฀ zoólogos,฀ mas฀ eu฀
diferente฀ de.฀ Para฀ testar฀ condições฀ em฀ if e ! -d l b não฀entendo฀nada฀de฀reino,฀fi฀lo,฀classe,฀
Shell฀Script฀usamos฀o฀comando฀test,฀só฀ he ordem,฀família,฀gênero,฀espécie฀e฀outras฀
que฀ele฀é฀muito฀mais฀poderoso฀do฀que฀ kdi l b coisas฀do฀tipo,฀desta฀forma฀o฀que฀estou฀
aquilo฀ com฀ que฀ estamos฀ acostuma- fi chamando฀de฀família฀ou฀de฀gênero฀tem฀
dos.฀ Primeiramente,฀ veja฀ na฀ Tabela฀ 1฀ cd l b grande฀chance฀de฀estar฀total฀e฀comple-
as฀ principais฀ opções฀ (existem฀ muitas฀ tamente฀incorreto:
outras)฀ para฀ testar฀ arquivos฀ em฀ disco฀ Desta฀ forma฀ o฀ diretório฀ lmb฀ seria฀
e฀na฀Tabela฀2฀as฀principais฀opções฀para฀ criado฀ somente฀ se฀ ele฀ ainda฀ não฀ exis- $ Fa ilia=feli ae
teste฀de฀cadeias฀de฀caracteres. tisse,฀e฀esta฀negativa฀deve-se฀ao฀ponto฀ $ Ge e =ga
de฀exclamação฀(!)฀precedendo฀a฀opção฀ $ if e $Fa ilia = ca idea U
Tabela฀3฀–฀Opções฀do -d.฀Ao฀fi฀m฀da฀execução฀desse฀fragmento฀ -a $Ge e = l b - $Fa ilia = U
test฀para฀números de฀script,฀com฀certeza฀o฀programa฀esta- feli a -a $Ge e = leã
ria฀dentro฀do฀diretório฀lmb.฀Vamos฀ver฀ > he
Opção Verdadeiro฀se Signifi฀cado
dois฀exemplos฀para฀entender฀a฀diferença฀ > ech C idad
n1฀-eq฀n2 n1฀e฀n2฀são฀iguais equal
na฀comparação฀entre฀números฀e฀entre฀ > el e
n1฀-ne฀n2 n1฀e฀n2฀não฀são฀iguais not฀equal
cadeias฀de฀caracteres. > ech P de a a a ã
n1฀-gt฀n2 n1฀é฀maior฀que฀n2 greater฀than
n1฀-ge฀n2 n1฀é฀maior฀ou฀igual฀a฀n2 greater฀or฀equal > fi
n1฀-lt฀n2 n1฀é฀menor฀que฀n2 less฀than cad = P de a a a ã
n1฀-le฀n2 n1฀é฀menor฀ou฀igual฀a฀n2 less฀or฀equal cad =
if e $cad = $cad Neste฀ exemplo,฀ caso฀ o฀ animal฀ fosse฀
he da฀família฀canídea฀e฀(-a)฀do฀gênero฀lobo,฀
Pensa฀que฀acabou?฀Engano฀seu!฀Agora฀ ech A a iá ei ã ig ai ou฀(-o)฀da฀familia฀felina฀e฀(-a)฀do฀gênero฀
é฀hora฀de฀algo฀mais฀familiar,฀as฀famosas฀ el e leão,฀seria฀dado฀um฀alerta,฀caso฀contrá-
comparações฀ com฀ valores฀ numéricos.฀ ech A a iá ei ã dife e e rio฀a฀mensagem฀seria฀de฀incentivo.
Veja฀ a฀ Tabela฀ 3,฀ e฀ some฀ às฀ opções฀ já฀ fi Atenção:฀ Os฀ sinais฀ de฀ maior฀ (>)฀ no฀
apresentadas฀os฀operadores฀da฀Tabela฀4. início฀ das฀ linhas฀ internas฀ ao฀ if฀ são฀ os฀
Ufa!฀ Como฀ você฀ viu,฀ tem฀ coisa฀ pra฀ Executando฀o฀fragmento฀de฀programa฀ prompts฀ de฀ continuação฀ (que฀ estão฀
chuchu,฀e฀o฀nosso฀if฀é฀muito฀mais฀pode- acima,฀teremos฀como฀resultado: defi฀nidos฀na฀variável฀$PS2).฀Quando฀o฀
roso฀ que฀ o฀ dos฀ outros.฀ Vamos฀ ver฀ em฀ shell฀ identifi฀ca฀ que฀ um฀ comando฀ con-
uns฀exemplos฀como฀isso฀tudo฀funciona.฀ A a iá ei ã dife e e tinuará฀ na฀ linha฀ seguinte,฀ automatica-
Testamos฀a฀existência฀de฀um฀diretório: mente฀ele฀coloca฀este฀caractere,฀até฀que฀
Vamos฀agora฀alterá-lo฀um฀pouco฀para฀ o฀comando฀seja฀encerrado.
if e -d l b que฀a฀comparação฀seja฀numérica: Vamos฀mudar฀o฀exemplo฀para฀ver฀se฀o฀
he programa฀continua฀funcionando:
cd l b cad =
el e cad = $ Fa ilia=feli
kdi l b if e $cad -e $cad $ Ge e =ga
cd l b he $ if e $Fa ilia = feli - U
fi ech A a iá ei ã ig ai $Fa ilia = ca ide -a $Ge e = U
el e ça - $Ge e = l b
Tabela฀4 ech A a iá ei ã dife e e > he
fi > ech C idad
Operador Finalidade > el e
Parênteses฀() 0
E฀vamos฀executá-lo฀novamente: > ech P de a a a ã
> fi
Exclamação฀! 0
A a iá ei ã ig ai C idad
-a 0
-o 0
Como฀você฀viu,฀nas฀duas฀execuções฀ Obviamente฀ a฀ operação฀ resultou฀ em฀
obtive฀ resultados฀ diferentes,฀ porque฀ a฀ erro,฀porque฀a฀opção฀-a฀tem฀precedência฀

�����������������������������
[Link]฀ edição฀04 85
��������������������������������������������������������������������������������
���������������������������������������������������
����������������������������������������������������������������������������������������������������������������������������������������������������
LINUX฀USER Papo฀de฀Botequim

sobre฀a฀-o฀e,฀dessa,฀forma฀o฀que฀foi฀ava- Da฀ mesma฀ forma,฀ para฀ escolhermos฀ mente฀a฀legibilidade,฀pois฀o฀comando฀if฀


liado฀primeiro฀foi฀a฀expressão: CDs฀ que฀ tenham฀ a฀ participação฀ do฀ irá฀fi฀car฀com฀a฀sintaxe฀semelhante฀à฀das฀
Artista1฀ e฀ do฀ Artista2,฀ não฀ é฀ necessá- outras฀linguagens;฀por฀isso,฀esse฀será฀o฀
$Fa ilia = ca ide -a $Ge e = U rio฀montar฀um฀if฀com฀o฀conector฀-o.฀O฀ modo฀como฀o฀comando฀test฀será฀usado฀
ça egrep฀ também฀ resolve฀ isso฀ para฀ nós.฀ daqui฀para฀a฀frente.
Veja฀como: Se฀você฀pensa฀que฀acabou,฀está฀muito฀
Que฀ foi฀ avaliada฀ como฀ falsa,฀ retor- enganado.฀Preste฀atenção฀à฀“Tabela฀Ver-
nando฀o฀seguinte: $ eg e A i a |A i a U dade”฀na฀Tabela฀5.
ica
$Fa ilia = feli - FALSO - U Tabela฀5฀-฀Tabela฀Verdade
$Ge e = l b Ou฀(nesse฀caso฀específi฀co)฀o฀próprio฀
Combinação E OU
grep฀poderia฀nos฀quebrar฀o฀galho:
VERDADEIRO-VERDADEIRO TRUE TRUE
Que฀resolvida฀resulta฀em:
VERDADEIRO-FALSO FALSE TRUE
$g e A i a[ ] ica FALSO-VERDADEIRO FALSE TRUE
VERDADEIRO - FALSO - FALSO FALSO-FALSO FALSE FALSE
No฀ egrep฀ acima,฀ foi฀ usada฀ uma฀
Como฀agora฀todos฀os฀conectores฀são฀ expressão฀regular,฀na฀qual฀a฀barra฀ver-
-o,฀e฀para฀que฀uma฀série฀de฀expressões฀ tical฀(|)฀trabalha฀como฀um฀“ou฀lógico”฀e฀ Ou฀ seja,฀ quando฀ o฀ conector฀ é฀ e฀ e฀ a฀
conectadas฀ entre฀ si฀ por฀ diversos฀ “ou”฀ os฀ parênteses฀ são฀ usados฀ para฀ limitar฀ primeira฀condição฀é฀verdadeira,฀o฀resul-
lógicos฀seja฀verdadeira,฀basta฀que฀uma฀ a฀ amplitude฀ deste฀ “ou”.฀ Já฀ no฀ grep฀ da฀
tado฀fi฀nal฀pode฀ser฀verdadeiro฀ou฀falso,฀
delas฀o฀seja.฀A฀expressão฀fi฀nal฀resultou฀ linha฀ seguinte,฀ a฀ palavra฀ Artista฀ deve฀dependendo฀da฀segunda฀condição;฀já฀no฀
como฀ VERDADEIRO฀ e฀ o฀ then฀ foi฀ exe- ser฀seguida฀por฀um฀dos฀valores฀da฀lista฀ conector฀ou,฀caso฀a฀primeira฀condição฀
cutado฀de฀forma฀errada.฀Para฀que฀isso฀ formada฀pelos฀colchetes฀([]),฀isto฀é,฀1฀ou฀2.
seja฀verdadeira,฀o฀resultado฀sempre฀será฀
volte฀a฀funcionar฀façamos฀o฀seguinte: verdadeiro.฀Se฀a฀primeira฀for฀falsa,฀o฀resul-
–฀ Tá฀ legal,฀ eu฀ aceito฀ o฀ argumento,฀ o฀ if฀ tado฀dependerá฀da฀segunda฀condição.
$ if e \ $Fa ilia = feli U do฀ shell฀ é฀ muito฀ mais฀ poderoso฀ que฀ Ora,฀ os฀ caras฀ que฀ desenvolveram฀ o฀
- $Fa ilia = ca ide \ -a U os฀outros฀caretas฀-฀mas,฀cá฀entre฀nós,฀ interpretador฀ não฀ são฀ bobos฀ e฀ estão฀
\ $Ge e = ça - $Ge e = U essa฀construção฀de฀if฀test฀...฀é฀muito฀ sempre฀ tentando฀ otimizar฀ ao฀ máximo฀
l b \ esquisita,฀é฀pouco฀legível. os฀ algoritmos.฀ Portanto,฀ no฀ caso฀ do฀
> he –฀ É,฀ você฀ tem฀ razão,฀ eu฀ também฀ não฀ conector฀e,฀a฀segunda฀condição฀não฀será฀
> ech C idad gosto฀disso฀e฀acho฀que฀ninguém฀gosta.฀ avaliada,฀caso฀a฀primeira฀seja฀falsa,฀já฀
> el e Acho฀ que฀ foi฀ por฀ isso฀ que฀ o฀ shell฀ que฀ o฀ resultado฀ será฀ sempre฀ falso.฀ Já฀
> ech P de a a a ã incorporou฀outra฀sintaxe,฀que฀substi- com฀ o฀ ou,฀ a฀ segunda฀ será฀ executada฀
> fi tui฀o฀comando฀test.฀ somente฀caso฀a฀primeira฀seja฀falsa.
P de a a a ã Aproveitando-se฀ disso,฀ uma฀ forma฀
Para฀ isso฀ vamos฀ pegar฀ aquele฀ exem- abreviada฀de฀fazer฀testes฀foi฀criada.฀O฀
Desta฀ forma,฀ com฀ o฀ uso฀ dos฀ parên- plo฀para฀fazer฀uma฀troca฀de฀diretórios,฀ conector฀e฀foi฀batizado฀de฀&&฀e฀o฀ou฀de฀
teses฀ agrupamos฀ as฀ expressões฀ com฀ o฀ que฀era฀assim: ||.฀Para฀ver฀como฀isso฀funciona,฀vamos฀
conector฀ -o,฀ priorizando฀ a฀ execução฀ e฀ usá-los฀ como฀ teste฀ no฀ nosso฀ velho฀
resultando฀em฀VERDADEIRO฀-a฀FALSO. if e ! -d l b exemplo฀de฀troca฀de฀diretório,฀que฀em฀
Para฀ que฀ seja฀ VERDADEIRO฀ o฀ resul- he sua฀última฀versão฀estava฀assim:
tado฀ de฀ duas฀ expressões฀ ligadas฀ pelo฀ kdi l b
conector฀ -a,฀ é฀ necessário฀ que฀ ambas฀ fi if [ ! -d l b ]
sejam฀verdadeiras,฀o฀que฀não฀é฀o฀caso฀ cd l b he
do฀exemplo฀acima.฀Assim,฀o฀resultado฀ kdi l b
fi฀nal฀foi฀FALSO,฀sendo฀então฀o฀else฀cor- e฀utilizando฀a฀nova฀sintaxe,฀vamos฀fazê- fi
retamente฀executado. lo฀assim: cd l b
Se฀ quisermos฀ escolher฀ um฀ CD฀ que฀
tenha฀faixas฀de฀2฀artistas฀diferentes,฀nos฀ if [ ! -d l b ] O฀código฀acima฀também฀poderia฀ser฀
sentimos฀tentados฀a฀usar฀um฀if฀com฀o฀ he escrito฀de฀maneira฀abreviada:
conector฀-a,฀mas฀é฀sempre฀bom฀lembrar฀ kdi l b
que฀o฀bash฀nos฀oferece฀muitos฀recursos฀ fi [ ! -d l b ] && kdi l b
e฀isso฀poderia฀ser฀feito฀de฀forma฀muito฀ cd l b cd di
mais฀simples฀com฀um฀único฀comando฀
grep,฀da฀seguinte฀forma: Ou฀ seja,฀ o฀ comando฀ test฀ pode฀ ser฀ Também฀podemos฀retirar฀a฀negação฀(!):
substituído฀por฀um฀par฀de฀colchetes฀([]),฀
$ g e A i a ica | g e U separados฀ por฀ espaços฀ em฀ branco฀ dos฀ [ -d l b ] || kdi l b
A i a argumentos,฀o฀que฀aumentará฀enorme- cd di

�����������������������������
86 edição฀04 [Link]฀
��������������������������������������������������������������������������������
����������������������������������������������������
�����������������������������������������������������������������������������������������������������������������������������������������������������
Papo฀de฀Botequim LINUX฀USER

Tabela฀6 diretório฀para฀dentro฀dele.฀Para฀execu- sempre฀estará฀dentro฀de฀lmb,฀desde฀que฀


tar฀mais฀de฀um฀comando฀dessa฀forma,฀ tenha฀permissão฀para฀entrar฀neste฀dire-
Caractere Signifi฀cado
é฀ necessário฀ fazer฀ um฀ grupamento฀ de฀ tório,฀permissão฀para฀criar฀um฀subdire-
* Qualquer฀caractere฀ocorrendo฀zero฀ou฀
comandos,฀ o฀ que฀ se฀ consegue฀ com฀ o฀ tório฀dentro฀de฀../lmb,฀que฀haja฀espaço฀
mais฀vezes
? Qualquer฀caractere฀ocorrendo฀uma฀vez
uso฀ de฀ chaves฀ ({}).฀ Veja฀ como฀ seria฀ o฀ em฀disco฀sufi฀ciente...
[...] Lista฀de฀caracteres modo฀correto: Vejamos฀um฀exemplo฀didático:฀depen-
| “ou”฀lógico฀ dendo฀do฀valor฀da฀variável฀$opc฀o฀script฀
cd l b || deverá฀ executar฀ uma฀ das฀ opções฀ a฀
{ seguir:฀inclusão,฀exclusão,฀alteração฀ou฀
No฀ primeiro฀ caso,฀ se฀ o฀ primeiro฀ kdi l b encerrar฀sua฀execução.฀Veja฀como฀fi฀ca-
comando฀ (o฀ test,฀ que฀ está฀ represen- cd l b ria฀o฀código:
tado฀pelos฀colchetes)฀for฀bem฀sucedido,฀ }
isto฀é,฀se฀o฀diretório฀lmb฀não฀existir,฀o฀ if [ $ c -e ]
comando฀mkdir฀será฀executado฀porque฀ Ainda฀ não฀ está฀ legal฀ porque,฀ caso฀ o฀ he
a฀primeira฀condição฀era฀verdadeira฀e฀o฀ diretório฀não฀exista,฀o฀cd฀exibirá฀uma฀ i cl a
conector฀era฀e. mensagem฀de฀erro.฀Veja฀o฀modo฀certo: elif [ $ c -e ]
No฀exemplo฀seguinte,฀testamos฀se฀o฀ he
diretório฀lmb฀existia฀(no฀anterior฀testa- cd l b > de ll || e cl a
mos฀se฀ele฀não฀existia)฀e,฀caso฀isso฀fosse฀ { elif [ $ c -e ]
verdade,฀ o฀ mkdir฀ não฀ seria฀ executado฀ kdi l b he
porque฀o฀conector฀era฀ou.฀Outra฀forma฀ cd l b al e aca
de฀escrever฀o฀programa: } elif [ $ c -e 4 ]
he
cd l b || kdi l b Como฀você฀viu,฀o฀comando฀if฀nos฀per- e i
mitiu฀ fazer฀ um฀ cd฀ seguro฀ de฀ diversas฀ el e
Nesse฀ caso,฀ se฀ o฀ comando฀ cd฀ fosse฀ maneiras.฀É฀sempre฀bom฀lembrar฀que฀o฀ ech Digi e a çã e e U
mal฀ sucedido,฀ o฀ diretório฀ lmb฀ seria฀ “seguro”฀a฀que฀me฀refi฀ro฀diz฀respeito฀ao฀ e 4
criado฀mas฀não฀seria฀feita฀a฀mudança฀de฀ fato฀de฀que฀ao฀fi฀nal฀da฀execução฀você฀ fi

�����������������������������
[Link]฀ edição฀04 87
��������������������������������������������������������������������������������
���������������������������������������������������
����������������������������������������������������������������������������������������������������������������������������������������������������
LINUX฀USER Papo฀de฀Botequim

Quadro฀1฀-฀Script ca e $ c i O฀comando฀date฀informa฀a฀data฀com-
bem-educado i cl a pleta฀do฀sistema฀e฀tem฀diversas฀opções฀
e cl a de฀ mascaramento฀ do฀ resultado.฀ Neste฀
! bi ba h
al e aca comando,฀ a฀ formatação฀ começa฀ com฀
P g a a be ed cad e
4 e i um฀sinal฀de฀mais฀(+)฀e฀os฀caracteres฀de฀
dá b -dia, b a- a de
* ech Digi e a çã U formatação฀vêm฀após฀um฀sinal฀de฀per-
b a- i e c f e a h a
e e e 4 centagem฀(%),฀assim฀o฀%H฀signifi฀ca฀a฀
H a=$ da e H
e ac hora฀do฀sistema.฀Dito฀isso,฀veja฀o฀exem-
ca e $H a i
plo฀no฀Quadro฀1.
| [ ] ech B Dia
Como฀ você฀ deve฀ ter฀ percebido,฀ eu฀ Peguei฀pesado,฀né?฀Que฀nada,฀vamos฀
usei฀o฀asterisco฀como฀última฀opção,฀isto฀ esmiuçar฀a฀resolução:
[ - ] ech B a Ta de
é,฀se฀o฀asterisco฀atende฀a฀qualquer฀coisa,฀
então฀ servirá฀ para฀ qualquer฀ coisa฀ que฀ 0?฀|฀1 [01]฀– ฀Zero฀seguido฀de฀qualquer฀
* ech B a N i e
não฀esteja฀no฀intervalo฀de฀1฀a฀4.฀Outra฀ coisa฀ (?),฀ ou฀ (|)฀ um฀ seguido฀ de฀ zero฀
coisa฀a฀ser฀notada฀é฀que฀o฀duplo฀ponto-e- ou฀um฀([01]),฀ou฀seja,฀esta฀linha฀"casa"฀
e ac
vírgula฀não฀é฀necessário฀antes฀do฀esac. com฀01,฀02,฀...฀09,฀10฀e฀11;
e i
Vamos฀ agora฀ fazer฀ um฀ script฀ mais฀ 1 [2-7]฀– ฀Signifi฀ca฀um฀seguido฀da฀lista฀
radical.฀Ele฀te฀dará฀bom฀dia,฀boa฀tarde฀ de฀caracteres฀entre฀dois฀e฀sete,฀ou฀seja,฀
Neste฀ exemplo฀ você฀ viu฀ o฀ uso฀ do฀ ou฀ boa฀ noite฀ dependendo฀ da฀ hora฀ em฀ esta฀linha฀pega฀12,฀13,฀...฀17;
comando฀ elif฀ como฀ um฀ substituto฀ ou฀ que฀for฀executado,฀mas฀primeiramente฀ *฀– ฀Signifi฀ca฀tudo฀o฀que฀não฀casou฀com฀
forma฀mais฀curta฀de฀else฀if.฀Essa฀é฀uma฀ veja฀estes฀comandos: nenhum฀dos฀padrões฀anteriores.
sintaxe฀válida฀e฀aceita,฀mas฀poderíamos฀
fazer฀ainda฀melhor.฀Para฀isso฀usamos฀o฀ $ da e –฀ Cara,฀ até฀ agora฀ eu฀ falei฀ muito฀ e฀ bebi฀
comando฀case,฀cuja฀sintaxe฀mostramos฀ T e N : : BRST 4 pouco.฀ Agora฀ eu฀ vou฀ te฀ passar฀ um฀
a฀seguir: $ da e H exercício฀ para฀ você฀ fazer฀ em฀ casa฀ e฀
me฀dar฀a฀resposta฀da฀próxima฀vez฀em฀
ca e $ a i que฀ nos฀ encontrarmos฀ aqui฀ no฀ bote-
ad a c d quim,฀tá฀legal?
c d –฀ Beleza!
c d –฀ É฀ o฀ seguinte:฀ faça฀ um฀ programa฀ que฀
ad a c d receba฀ como฀ parâmetro฀ o฀ nome฀ de฀
c d um฀arquivo฀e฀que฀quando฀executado฀
c d salve฀esse฀arquivo฀com฀o฀nome฀origi-
ad a c d nal฀seguido฀de฀um฀til฀(~)฀e฀abra฀esse฀
c d arquivo฀dentro฀do฀vi฀para฀ser฀editado.฀
c d Isso฀ é฀ para฀ ter฀ sempre฀ uma฀ cópia฀
e ac de฀ backup฀ do฀ arquivo฀ caso฀ alguém฀
faça฀ alterações฀ indevidas.฀ Obvia-
Onde฀a฀variável฀$var฀é฀comparada฀aos฀ mente,฀ você฀ fará฀ as฀ críticas฀ neces-
padrões฀padrao1,฀...,฀padraon.฀Caso฀um฀ sárias,฀como฀verifi฀car฀se฀foi฀passado฀
dos฀padrões฀corresponda฀à฀variável,฀o฀ um฀parâmetro,฀se฀o฀arquivo฀indicado฀
bloco฀de฀comandos฀cmd1,฀...,฀cmdn฀cor- existe...฀Enfi฀m,฀o฀que฀te฀der฀na฀telha฀e฀
respondente฀é฀executado฀até฀encontrar฀ você฀achar฀que฀deva฀constar฀do฀script.฀
um฀duplo฀ponto-e-vírgula฀(;;),฀quando฀ Deu฀pra฀entender?
o฀fl฀uxo฀do฀programa฀será฀interrompido฀ –฀ Hum,฀hum...
e฀ desviado฀ para฀ instrução฀ imediata- –฀ Chico,฀traz฀mais฀um,฀sem฀colarinho!฀■
mente฀após฀o฀comando฀esac฀(que,฀caso฀
não฀tenham฀notado,฀฀é฀case฀ao฀contrário.฀ Julio฀Cezar฀Neves฀é฀
Ele฀indica฀o฀fi฀m฀do฀bloco฀de฀código,฀da฀ Analista฀de฀Suporte฀
de฀Sistemas฀desde฀
SOBRE฀O฀AUTOR

mesma฀forma฀que฀ot฀comando฀fi฀฀indica฀
1969฀e฀trabalha฀com฀
o฀fi฀m฀de฀um฀if). Unix฀desde฀1980,฀
Na฀formação฀dos฀padrões,฀são฀aceitos฀ quando฀participou฀
os฀caracteres฀mostrados฀na฀Tabela฀6. do฀desenvolvimento฀
Para฀ mostrar฀ como฀ o฀ código฀ fica฀ do฀SOX,฀um฀sistema฀
operacional฀similar฀ao฀Unix฀pro-
melhor,฀vamos฀repetir฀o฀exemplo฀ante-
duzido฀pela฀Cobra฀computadores.฀
rior,฀só฀que฀desta฀vez฀usaremos฀o฀case฀ Pode฀ser฀contatado฀no฀e-mail฀julio.
em฀vez฀do฀tradicional฀bloco฀de฀código฀ neves@[Link]
com฀if฀...฀elif฀...฀else฀...฀fi฀.

�����������������������������
88 edição฀04 [Link]฀
��������������������������������������������������������������������������������
����������������������������������������������������
�����������������������������������������������������������������������������������������������������������������������������������������������������
Papo฀de฀Botequim LINUX฀USER

Curso฀de฀Shell฀Script

Papo฀de฀
Botequim฀V
Blocos฀de฀código฀e฀laços฀(ou฀loops,฀como฀preferem฀alguns)฀
Dave฀Hamilton฀-฀[Link]

são฀o฀tema฀do฀mês฀em฀mais฀uma฀lição฀de฀nosso฀curso฀de฀Shell฀

Script.฀Garçom,฀salta฀uma฀boa฀redondinha,฀que฀tô฀a฀fi฀m฀de฀

refrescar฀o฀pensamento!฀POR฀JULIO฀CEZAR฀NEVES

F
–฀
ala฀ cara!฀ E฀ as฀ idéias฀ estão฀ em฀
ordem?฀Já฀fundiu฀a฀cuca฀ou฀você฀
ainda฀agüenta฀mais฀Shell?
Güento!฀ Tô฀ gostando฀ muito!฀ Gostei฀
tanto฀ que฀ até฀ caprichei฀ no฀ exercício฀
Até฀agora฀já฀vimos฀alguns฀blocos฀de฀
código,฀ como฀ quando฀ te฀ mostrei฀ um฀
exemplo฀para฀fazer฀um฀cd฀para฀dentro฀
de฀um฀diretório:
$ ca
! bi
Quadro฀1:฀[Link]
i a h
ba h

que฀ você฀ passou.฀ Lembra฀ que฀ você฀ cd l b > de ll || i a - i e g a da d


me฀ pediu฀ para฀ fazer฀ um฀ programa฀ { a i a e i
que฀recebe฀como฀parâmetro฀o฀nome฀ kdi l b Ve ifica e alg a â e f i
de฀ um฀ arquivo฀ e฀ que฀ quando฀ execu- cd l b a ad
tado฀salva฀esse฀arquivo฀com฀o฀nome฀ } if [ $ - e ]
original฀ seguido฀ de฀ um฀ til฀ (~)฀ e฀ o฀ he
abre฀dentro฀do฀vi? O฀ fragmento฀ contido฀ entre฀ as฀ duas฀ ech E -> U : $ U฀
–฀ Claro฀que฀lembro,฀me฀mostre฀e฀expli- chaves฀({})฀forma฀um฀bloco฀de฀código.฀ <a i >
que฀como฀você฀fez. Também฀nesse฀exercício฀que฀acabamos฀ e i
–฀ Beleza,฀dá฀uma฀olhada฀no฀quadro฀1 de฀ver,฀em฀que฀salvamos฀o฀arquivo฀antes฀ fi
–฀ É,฀beleza!฀Mas฀me฀diz฀uma฀coisa:฀por฀ de฀ editá-lo,฀ existem฀ vários฀ blocos฀ de฀ A =$
que฀ você฀ terminou฀ o฀ programa฀ com฀ código฀compreendidos฀entre฀os฀coman- Ca a i ã e i a, ã
um฀exit฀0? dos฀then฀e฀fi฀฀do฀if.฀Um฀bloco฀de฀código฀ há c ia a e al a
–฀ Eu฀ descobri฀ que฀ o฀ número฀ após฀ o฀ também฀pode฀estar฀dentro฀de฀um฀case฀ if [ ! -f $A ]
exit฀ indica฀ o฀ código฀ de฀ retorno฀ do฀ ou฀entre฀um฀do฀e฀um฀done. he
programa฀ (o฀ $?,฀ lembra?)฀ e฀ assim,฀ –฀ Peraí,฀Julio,฀que฀do฀e฀done฀são฀esses?฀ i $A
como฀ a฀ execução฀ foi฀ bem฀ sucedida,฀ Não฀ me฀ lembro฀ de฀ você฀ ter฀ falado฀ e i
ele฀ encerra฀ com฀ o฀ $?=0.฀ Porém,฀ se฀ nisso,฀ e฀ olha฀ que฀ estou฀ prestando฀ fi
você฀ observar,฀ verá฀ que฀ caso฀ o฀ pro- muita฀atenção... Se e ã de al e a
grama฀não฀tenha฀recebido฀o฀nome฀do฀ –฀ Pois฀é,฀ainda฀não฀tinha฀falado฀porque฀ a i , a i a a e
arquivo฀ou฀caso฀o฀operador฀não฀tenha฀ não฀havia฀chegado฀a฀hora฀certa.฀ if [ ! - $A ]
permissão฀de฀gravação฀nesse฀arquivo,฀ Todas฀ as฀ instruções฀ de฀ loop฀ ou฀ laço฀ he
o฀ código฀ de฀ retorno฀ ($?)฀ seria฀ dife- executam฀ os฀ comandos฀ do฀ bloco฀ com- ech V cê ã e e i ã U
rente฀do฀zero. preendidos฀entre฀um฀do฀e฀um฀done.฀As฀ de e c i a e $A
–฀ Grande฀garoto,฀aprendeu฀legal,฀mas฀é฀ instruções฀de฀loop฀ou฀laço฀são฀for,฀while฀ e i
bom฀deixar฀claro฀que฀exit฀0,฀simples- e฀ until฀ ,฀ que฀ serão฀ explicadas฀ uma฀ a฀ fi
mente฀exit฀ou฀não฀colocar฀exit฀produ- uma฀a฀partir฀de฀hoje. Já e e á d OK,
zem฀igualmente฀um฀código฀de฀retorno฀ al a a c ia e cha a i
($?)฀igual฀a฀zero.฀Agora฀vamos฀falar฀ O฀comando฀For c -f $A $A ~
sobre฀ as฀ instruções฀ de฀ loop฀ ou฀ laço,฀ Se฀ você฀ está฀ habituado฀ a฀ programar,฀ i $A
mas฀ antes฀ vou฀ passar฀ o฀ conceito฀ de฀ certamente฀ já฀ conhece฀ o฀ comando฀ for,฀ e i
bloco฀de฀código. mas฀ o฀ que฀ você฀ não฀ sabe฀ é฀ que฀ o฀ for,฀

�����������������������������
[Link]฀ edição฀05 89
��������������������������������������������������������������������������������
���������������������������������������������������
����������������������������������������������������������������������������������������������������������������������������������������������������
LINUX฀USER Papo฀de฀Botequim

que฀é฀uma฀instrução฀intrínseca฀do฀Shell฀ Então฀vamos฀executá-lo: $ ech $IFS | d -h


(isso฀ signifi฀ca฀ que฀ o฀ código฀ fonte฀ do฀ a a
comando฀faz฀parte฀do฀código฀fonte฀do฀ $ e ef 4
Shell,฀ou฀seja,฀em฀bom฀programês฀é฀um฀ A D DOS :c f :i c :
built-in),฀é฀muito฀mais฀poderoso฀que฀os฀ l gad : e c: ica : i c: Isto฀ é,฀ mandei฀ a฀ variável฀ (protegida฀
seus฀correlatos฀das฀outras฀linguagens. li :$ da฀ interpretação฀ do฀ Shell฀ pelas฀ aspas)฀
Vamos฀ entender฀ a฀ sua฀ sintaxe,฀ pri- para฀um฀dump฀hexadecimal฀(od฀-h).฀O฀
meiro฀ em฀ português฀ e,฀ depois,฀ como฀ Como฀você฀viu,฀o฀Shell฀transformou฀ resultado฀pode฀ser฀interpretado฀com฀a฀
funciona฀pra฀valer.฀Olhe฀só: o฀ asterisco฀ (que฀ odeia฀ ser฀ chamado฀ tabela฀abaixo:
de฀ asterístico)฀ em฀ uma฀ lista฀ de฀ arqui-
a a a e al al al vos฀ separados฀ por฀ espaços฀ em฀ branco.฀ Tabela฀1:฀Resultado฀do฀od฀-h
faça Quando฀ o฀ for฀ viu฀ aquela฀ lista,฀ disse:฀
c d “Opa,฀ listas฀ separadas฀ por฀ espaços฀ é฀ Valor฀Hexadecimal Signifi฀cado

c d comigo฀mesmo!” 09 <TAB>

c d O฀bloco฀de฀comandos฀a฀ser฀executado฀ 20 <ESPAÇO>
fei era฀somente฀o฀echo,฀que฀com฀a฀opção฀-n฀ 0a <ENTER>
listou฀a฀variável฀$Arq฀seguida฀de฀dois-
Onde฀a฀variável฀var฀assume฀cada฀um฀ pontos฀(:),฀sem฀saltar฀a฀linha.฀O฀cifrão฀
dos฀valores฀da฀lista฀val1฀val2฀...฀valn฀e,฀ ($)฀ do฀ fi฀nal฀ da฀ linha฀ da฀ execução฀ é฀ o฀ O฀ último฀ 0a฀ foi฀ proveniente฀ do฀
para฀cada฀um฀desses฀valores,฀executa฀o฀ prompt,฀ que฀ permaneceu฀ na฀ mesma฀ <ENTER>฀ dado฀ ao฀ fi฀nal฀ do฀ comando.฀
bloco฀de฀comandos฀formado฀por฀cmd1,฀ linha฀também฀em฀função฀da฀opção฀-n.฀ Para฀melhorar฀a฀explicação,฀vamos฀ver฀
cmd2฀ e฀ cmdn.฀ Agora฀ que฀ já฀ vimos฀ o฀ Outro฀exemplo฀simples฀(por฀enquanto): isso฀de฀outra฀forma:
signifi฀cado฀da฀instrução฀em฀português,฀
vejamos฀a฀sintaxe฀correta: $ ca e ef $ ech :$IFS: | ca - e
! bi ba h : ^I$
f a i al al al P g a a didá ic a a :$
d e e de f
c d f Pala a i Li Maga i e U No฀ comando฀ cat,฀ a฀ opção฀ -e฀ repre-
c d d B a il senta฀o฀<ENTER>฀como฀um฀cifrão฀($)฀
c d d e฀a฀opção฀-t฀representa฀o฀<TAB>฀como฀
d e ech $Pala a um฀^I.฀Usei฀os฀dois-pontos฀(:)฀para฀mos-
d e trar฀ o฀ início฀ e฀ o฀ fi฀m฀ do฀ echo.฀ E฀ dessa฀
Vamos฀ aos฀ exemplos,฀ para฀ entender฀ forma,฀pudemos฀notar฀que฀os฀três฀carac-
direito฀o฀funcionamento฀deste฀comando.฀ E฀executando฀temos: teres฀estão฀presentes฀naquela฀variável.฀
Vamos฀ escrever฀ um฀ script฀ para฀ listar฀ Agora฀veja฀você:฀traduzindo,฀IFS฀sig-
todos฀os฀arquivos฀do฀diretório,฀separa- $ e ef nifi฀ca฀separador฀entre฀campos.฀Uma฀vez฀
dos฀por฀dois-pontos,฀mas฀antes฀veja฀isso: Li entendido฀isso,฀eu฀posso฀afi฀rmar฀que฀o฀
Maga i e comando฀for฀não฀usa฀apenas฀listas฀sepa-
$ ech * d radas฀por฀espaços฀em฀branco,฀mas฀sim฀
A D DOS c f i c B a il pelo฀ conteúdo฀ da฀ variável฀ $IFS,฀ cujo฀
l gad e c ica i c valor฀padrão฀são฀os฀caracteres฀que฀aca-
li Como฀ você฀ viu,฀ esse฀ exemplo฀ é฀ bamos฀de฀ver.฀Para฀comprovarmos฀isso,฀
tão฀ bobo฀ e฀ simples฀ como฀ o฀ anterior,฀ vamos฀ continuar฀ mexendo฀ em฀ nossa฀
Isto฀ é,฀ o฀ Shell฀ viu฀ o฀ asterisco฀ (*),฀ mas฀ serve฀ para฀ mostrar฀ o฀ comporta- CDTeca,฀ escrevendo฀ um฀ script฀ que฀
expandiu-o฀ com฀ o฀ nome฀ de฀ todos฀ os฀ mento฀básico฀do฀for.฀Veja฀só฀a฀força฀do฀ recebe฀o฀nome฀do฀artista฀como฀parâme-
arquivos฀do฀diretório฀e฀o฀comando฀echo฀ comando:฀ ainda฀ estamos฀ na฀ primeira฀ tro฀e฀lista฀as฀músicas฀que฀ele฀toca.฀Mas฀
jogou-os฀para฀a฀tela฀separados฀por฀espa- possibilidade฀de฀sintaxe฀e฀já฀estou฀mos- primeiramente฀vamos฀ver฀como฀está฀o฀
ços฀em฀branco.฀Visto฀isso,฀vamos฀resol- trando฀novas฀formas฀de฀usá-lo.฀Lá฀atrás฀ nosso฀arquivo฀musicas:
ver฀o฀problema฀a฀que฀nos฀propusemos: eu฀ havia฀ falado฀ que฀ o฀ for฀ usava฀ listas฀
separadas฀por฀espaços฀em฀branco,฀mas฀ $ ca ica
$ ca e ef isso฀é฀uma฀meia-verdade,฀só฀para฀facili- alb ^A i a ~M ica : U
! bi ba h tar฀a฀compreensão.฀Na฀verdade,฀as฀listas฀ A i a ~M ica
P g a a didá ic a a não฀são฀obrigatoriamente฀separadas฀por฀ alb ^A i a ~M ica : U
e e de f espaços.฀Mas฀antes฀de฀prosseguir,฀pre- A i a4~M ica4
f A i * ciso฀te฀mostrar฀como฀se฀comporta฀uma฀ alb ^A i a5~M ica5: U
d variável฀do฀sistema฀chamada฀de฀IFS,฀ou฀ A i a ~M ica
ech - $A : Inter฀Field฀Separator฀Veja฀no฀exemplo฀a฀ alb 4^A i a ~M ica : U
d e seguir฀seu฀conteúdo: A i a ~M ica

�����������������������������
90 edição฀05 [Link]฀
��������������������������������������������������������������������������������
����������������������������������������������������
�����������������������������������������������������������������������������������������������������������������������������������������������������
Papo฀de฀Botequim LINUX฀USER

alb 5^A i a ~M ica : U o฀$1฀seria฀Perereca฀e฀o฀resto฀desse฀lindo฀ $ li a i a A i a


A i a ~M ica nome฀seria฀ignorado฀na฀pesquisa. M ica
Para฀que฀isso฀não฀ocorra,฀eu฀deveria฀ M ica
Em฀cima฀desse฀“leiaute”฀desenvolve- passar฀o฀nome฀do฀artista฀entre฀aspas฀
mos฀o฀script฀a฀seguir: (”)฀ou฀trocar฀$1฀por฀$*฀(que฀representa฀ Veja฀uma฀segunda฀sintaxe฀para฀o฀for:
todos฀os฀parâmetros฀passados),฀que฀é฀
$ ca li a i a a฀melhor฀solução,฀mas฀nesse฀caso฀eu฀ f a
! bi ba h teria฀que฀modifi฀car฀a฀crítica฀dos฀parâ- d
Dad a i a, a a metros฀ e฀ o฀ grep.฀ A฀ nova฀ versão฀ não฀ c d
a ica seria฀se฀eu฀passei฀um฀parâmetro,฀mas฀ c d
if [ $ - e ] sim฀ se฀ passei฀ pelo฀ menos฀ um฀ parâ- c d
he metro.฀Quanto฀ao฀grep,฀veja฀só฀o฀que฀ d e
ech V cê de e ia e U aconteceria฀ após฀ a฀ substituição฀ do฀ $*฀
a ad a â e pelos฀parâmetros: Ué,฀sem฀o฀in,฀como฀ele฀vai฀saber฀que฀
e i valor฀assumir?฀Pois฀é,฀né?฀Esta฀constru-
fi ech $A M | g e e e eca U ção,฀à฀primeira฀vista,฀parece฀esquisita,฀
IFS= & e eleca mas฀é฀bastante฀simples.฀Neste฀caso,฀var฀
: assumirá฀um฀a฀um฀cada฀parâmetro฀pas-
f A M i $ c -f -d^ U Isso฀gera฀um฀erro.฀O฀correto฀é: sado฀para฀o฀programa.฀Como฀exemplo฀
ica para฀entender฀melhor,฀vamos฀fazer฀um฀
d ech $A M | g e -i U script฀que฀receba฀como฀parâmetro฀um฀
ech $A M | g e $ && U e e eca & e eleca monte฀de฀músicas฀e฀liste฀seus฀autores:
ech $A M | c -f -d~
d e Aqui฀ adicionamos฀ a฀ opção฀ -i฀ para฀ $ ca li a ica
que฀a฀pesquisa฀ignorasse฀maiúsculas฀e฀ ! bi ba h
O฀ script,฀ como฀ sempre,฀ começa฀ tes- minúsculas.฀ As฀ aspas฀ foram฀ inseridas฀ Recebe a e d e de
tando฀se฀os฀parâmetros฀foram฀passados฀ para฀que฀o฀nome฀do฀artista฀fosse฀visto฀ ica c a â e e
corretamente,฀em฀seguida฀o฀IFS฀foi฀confi฀- como฀uma฀só฀cadeia฀de฀caracteres.฀ li a i é e e Se
gurado฀para฀<ENTER>฀e฀dois-pontos฀(:)฀ Falta฀consertar฀o฀erro฀dele฀ter฀listado฀o฀ e f c , de e
(como฀demonstram฀as฀aspas฀em฀linhas฀ Artista10.฀O฀melhor฀é฀dizer฀ao฀grep฀que฀a฀ e a ad e e a a
diferentes),฀porque฀é฀ele฀quem฀separa฀os฀ cadeia฀de฀caracteres฀está฀no฀início฀(^)฀de e E ã cach ã
blocos฀Artistan~Musicam.฀Desta฀forma,฀ $ArtMus฀e฀que฀logo฀após฀vem฀um฀til฀(~).฀É฀ Ch a i h de Mãe
a฀variável฀$ArtMus฀irá฀receber฀cada฀um฀ preciso฀redirecionar฀a฀saída฀do฀grep฀para฀/
desses฀blocos฀do฀arquivo฀(repare฀que฀o฀ dev/null฀para฀que฀os฀blocos฀não฀sejam฀lis- if [ $ -e ]
for฀já฀recebe฀os฀registros฀sem฀o฀álbum฀ tados.฀Veja฀a฀nova฀cara฀do฀programa: he
em฀virtude฀do฀cut฀na฀sua฀linha).฀Caso฀ ech U : $ ica U
encontre฀o฀parâmetro฀($1)฀no฀bloco,฀o฀ $ ca li a i a [ ica ] [ ica ]
segundo฀cut฀listará฀somente฀o฀nome฀da฀ ! bi ba h e i
música.฀Vamos฀executar฀o฀programa: Dad a i a, a a fi
a ica IFS=
$ li a i a A i a Ve a :
A i a ~M ica if [ $ -e ] f M ica
M ica he d
A i a ~M ica ech V ce de e ia e U ech $M ica
M ica a ad el e a a e S =$ g e -i $M ica U
A i a ~M ica e i ica ||
M ica fi {
IFS= ech Nã U
Êpa!฀ Aconteceram฀ duas฀ coisas฀ inde- : e c ada
sejáveis:฀os฀blocos฀também฀foram฀lista- f A M i $ c -f -d^ U c i e
dos,฀e฀a฀Musica10฀idem.฀Além฀do฀mais,฀ ica }
o฀nosso฀arquivo฀de฀músicas฀está฀muito฀ d f A M i $ ech $S U
simples:฀ na฀ vida฀ real,฀ tanto฀ a฀ música฀ ech $A M | g e -i U | c -f -d^
quanto฀o฀artista฀têm฀mais฀de฀um฀nome.฀ ^$*~ > de ll && ech U d
Suponha฀que฀o฀artista฀fosse฀uma฀dupla฀ $A M | c -f -d~ ech $A M | U
sertaneja฀chamada฀Perereca฀&฀Peteleca฀ d e g e -i $M ica | c -f -d~
(não฀gosto฀nem฀de฀dar฀a฀idéia฀com฀receio฀ d e
que฀isso฀se฀torne฀realidade).฀Nesse฀caso,฀ O฀resultado฀é: d e

�����������������������������
[Link]฀ edição฀05 91
��������������������������������������������������������������������������������
���������������������������������������������������
����������������������������������������������������������������������������������������������������������������������������������������������������
LINUX฀USER Papo฀de฀Botequim

Da฀mesma฀forma฀que฀os฀outros,฀come- Ou฀na฀forma฀mais฀completa฀do฀seq: Repare฀ que฀ o฀ incremento฀ saiu฀ do฀


çamos฀o฀exercício฀com฀uma฀crítica฀sobre฀ corpo฀do฀for฀e฀passou฀para฀o฀bloco฀de฀
os฀ parâmetros฀ recebidos,฀ em฀ seguida฀ f i i $ e código;฀ repare฀ também฀ que,฀ quando฀
fizemos฀ um฀ for฀ em฀ que฀ a฀ variável฀ d usei฀ o฀ let,฀ não฀ foi฀ necessário฀ iniciali-
$Musica฀receberá฀cada฀um฀dos฀parâme- ech - $i zar฀a฀variável฀$i.฀Veja฀só฀os฀comandos฀a฀
tros฀passados,฀colocando฀em฀$Str฀todos฀ d e seguir,฀digitados฀diretamente฀no฀prompt,฀
os฀álbuns฀que฀contêm฀as฀músicas฀dese- para฀demonstrar฀o฀que฀acabo฀de฀falar:
jadas.฀Em฀seguida,฀o฀outro฀for฀pega฀cada฀
bloco฀Artista~Musica฀nos฀registros฀que฀ A฀ outra฀ forma฀ de฀ fazer฀ isso฀ é฀ com฀ $ ech $j
estão฀ em฀ $Str฀ e฀ lista฀ cada฀ artista฀ que฀ uma฀sintaxe฀muito฀semelhante฀ao฀for฀da฀ $ le j
toca฀aquela฀música.฀Vamos฀executar฀o฀ linguagem฀C,฀como฀vemos฀a฀seguir: $ ech $j
programa฀para฀ver฀se฀funciona฀mesmo:
f a =i i c d i c
$ li a ica ica M ica4 U d Ou฀seja,฀a฀variável฀$j฀sequer฀existia฀e฀
Eg i ha P c c d no฀primeiro฀let฀assumiu฀o฀valor฀0฀(zero)฀
ica c d para,฀após฀o฀incremento,฀ter฀o฀valor฀1.฀
A i a c d Veja฀só฀como฀as฀coisas฀fi฀cam฀simples:
A i a d e
M ica4 f a i *
A i a4 Onde฀ var=ini฀ signifi฀ca฀ que฀ a฀ variá- d
Eg i ha P c vel฀ var฀ começará฀ de฀ um฀ valor฀ inicial฀ le i
Nã e c ada ini;฀cond฀signifi฀ca฀que฀o฀loop฀ou฀laço฀for฀ ech $i -> $A
será฀executado฀enquanto฀var฀não฀atingir฀ d e
A฀listagem฀fi฀cou฀feinha฀porque฀ainda฀ a฀condição฀cond฀e฀incr฀signifi฀ca฀o฀incre- -> A D DOS
não฀ sabemos฀ formatar฀ a฀ saída;฀ mas฀ mento฀que฀a฀variável฀var฀sofrerá฀a฀cada฀ -> c f
qualquer฀dia฀desses,฀quando฀você฀sou- passada฀do฀loop.฀Vamos฀aos฀exemplos: -> i c
ber฀posicionar฀o฀cursor,฀trabalhar฀com฀ 4 -> li a ica
cores฀etc.,฀faremos฀esse฀programa฀nova- f i= i<= i 5 -> li a i a
mente฀usando฀todas฀essas฀perfumarias. d -> l gad
A฀ esta฀ altura฀ dos฀ acontecimentos,฀ ech - $i -> e c
você฀ deve฀ estar฀ se฀ perguntando:฀ “E฀ d e 8 -> ica
aquele฀for฀tradicional฀das฀outras฀lingua- 4 5 8 -> i c
gens฀em฀que฀ele฀sai฀contando฀a฀partir฀ -> li
de฀ um฀ número,฀ com฀ um฀ determinado฀ A฀variável฀i฀partiu฀do฀valor฀inicial฀1,฀o฀ -> e ef
incremento,฀ até฀ alcançar฀ uma฀ condi- bloco฀de฀código฀(aqui฀somente฀o฀echo)฀ -> e ef
ção?”.฀ E฀ é฀ aí฀ que฀ eu฀ te฀ respondo:฀ “Eu฀ será฀executado฀enquanto฀i฀for฀menor฀ou฀
não฀te฀disse฀que฀o฀nosso฀for฀é฀mais฀por- igual฀(<=)฀a฀9฀e฀o฀incremento฀de฀i฀será฀ –฀ Pois฀é฀amigo,฀tenho฀certeza฀que฀você฀
reta฀que฀o฀dos฀outros?”฀Para฀fazer฀isso,฀ de฀1฀a฀cada฀passada฀do฀loop. já฀ tomou฀ um฀ xarope฀ do฀ comando฀
existem฀ duas฀ formas.฀ Com฀ a฀ primeira฀ Repare฀que฀no฀for฀propriamente฀dito฀ for.฀ Por฀ hoje฀ chega,฀ na฀ próxima฀ vez฀
sintaxe฀que฀vimos,฀como฀no฀exemplo: (e฀não฀no฀bloco฀de฀código)฀não฀coloquei฀ em฀que฀nos฀encontrarmos฀falaremos฀
um฀ cifrão฀ ($)฀ antes฀ do฀ i฀ e฀ a฀ notação฀ sobre฀outras฀instruções฀de฀loop,฀mas฀
f i i $ e para฀incrementar฀(i++)฀é฀diferente฀do฀ eu฀gostaria฀que฀até฀lá฀você฀fi฀zesse฀um฀
d que฀vimos฀até฀agora.฀O฀uso฀de฀parênte- pequeno฀script฀para฀contar฀a฀quanti-
ech - $i ses฀duplos฀(assim฀como฀o฀comando฀let)฀ dade฀de฀palavras฀de฀um฀arquivo฀texto,฀
d e chama฀ o฀ interpretador฀ aritmético฀ do฀ cujo฀nome฀seria฀recebido฀como฀parâ-
4 5 8 Shell,฀que฀é฀mais฀tolerante. metro.฀ Essa฀ contagem฀ tem฀ que฀ ser฀
Só฀para฀mostrar฀como฀o฀let฀funciona฀ feita฀com฀o฀comando฀for,฀para฀se฀habi-
A฀variável฀i฀assumiu฀os฀valores฀intei- e฀a฀versatilidade฀do฀for,฀vamos฀fazer฀a฀ tuar฀ao฀seu฀uso.฀Não฀vale฀usar฀o฀wc฀-w.฀
ros฀ entre฀ 1฀ a฀ 9฀ gerados฀ pelo฀ comando฀ mesma฀ coisa,฀ mas฀ omitindo฀ a฀ última฀ Aê฀Chico!฀Traz฀a฀saideira!฀ ■
seq฀e฀a฀opção฀-n฀do฀echo฀foi฀usada฀para฀ parte฀do฀escopo฀do฀for,฀passando-a฀para฀
não฀saltar฀uma฀linha฀a฀cada฀número฀lis- o฀bloco฀de฀código: Julio฀Cezar฀Neves฀é฀Analista฀de฀
SOBRE฀O฀AUTOR

tado.฀Ainda฀usando฀o฀for฀com฀seq: Suporte฀de฀Sistemas฀desde฀1969฀e฀tra-
f i<= balha฀com฀Unix฀desde฀1980,฀quando฀
f i i $ e 4 d participou฀do฀desenvolvimento฀do฀
d le i SOX,฀um฀sistema฀operacional฀similar฀
ech - $i ech - $i ao฀Unix฀produzido฀pela฀Cobra฀Com-
putadores.฀Pode฀ser฀contatado฀no฀
d e d e
e-mail฀[Link]@[Link]
4 5 8 4 5 8

�����������������������������
92 edição฀05 [Link]฀
��������������������������������������������������������������������������������
���������������������������������������������������
����������������������������������������������������������������������������������������������������������������������������������������������������
LINUX฀USER Papo฀de฀Botequim

Curs�฀�e฀Shell฀S�ript

Papo฀de฀
Botequim฀VI
Blocos฀de฀código฀e฀laços฀(ou฀loops,฀como฀preferem฀alguns)฀
Dave฀Hamilt��฀-฀[Link]�.hu

são฀o฀tema฀do฀mês฀em฀mais฀uma฀lição฀de฀nosso฀curso฀de฀Shell฀

Script.฀Garçom,฀salta฀uma฀boa฀redondinha,฀que฀tô฀a฀fi฀m฀de฀

refrescar฀o฀pensamento!฀POR฀J�LIO฀CEZAR฀NEVES

F ala,฀cara!฀E฀aí,฀já฀tá฀sabendo฀tudo฀
do฀comando฀for?฀Eu฀te฀deixei฀um฀
exercício฀para฀treinar,฀se฀não฀me฀
engano฀era฀para฀contar฀a฀quantidade฀de฀
palavras฀de฀um฀arquivo...฀Você฀fez?
Ou฀ seja,฀ o฀ programa฀ começa,฀ como฀
sempre,฀ verifi฀cando฀ se฀ a฀ passagem฀ de฀
parâmetros฀ foi฀ correta;฀ em฀ seguida฀ o฀
comando฀for฀se฀incumbe฀de฀pegar฀cada฀
uma฀das฀palavras฀(lembre-se฀que฀o฀$IFS฀
Uma฀vez฀que฀chegamos฀neste฀ponto,฀
creio฀ser฀interessante฀citar฀que฀o฀Shell฀
trabalha฀com฀o฀conceito฀de฀“Expansão฀
Aritmética”฀ (Arithmetic฀ Expansion),฀
que฀é฀acionada฀por฀uma฀construção฀da฀
–฀ Claro!฀ Tô฀ empolgadão฀ com฀ essa฀ lin- padrão฀é฀branco,฀TAB฀e฀ENTER,฀que฀é฀ forma฀$((expressão))฀ou฀let฀expressão.
guagem!฀ Eu฀ fi฀z฀ da฀ forma฀ que฀ você฀ exatamente฀o฀que฀desejamos฀para฀sepa- No฀ último฀ loop฀ for฀ usei฀ a฀ expansão฀
pediu,฀olha฀só... rar฀as฀palavras),฀incrementando฀a฀vari- aritmética฀ das฀ duas฀ formas,฀ mas฀ não฀
–฀ Êpa!฀ Peraí฀ que฀ eu฀ tô฀ sequinho฀ pra฀ ável฀$Cont.฀Vamos฀relembrar฀como฀é฀o฀ podemos฀seguir฀adiante฀sem฀saber฀que฀
tomar฀um฀chope.฀Aê฀Chico,฀traz฀dois฀ arquivo฀[Link]. a฀expressão฀pode฀ser฀uma฀das฀listadas฀
por฀favor.฀Um฀sem฀colarinho! na฀tabela฀1.
–฀ Como฀eu฀ia฀dizendo,฀olha฀como฀eu฀fi฀z.฀ $ ca A D DOS Mas฀você฀pensa฀que฀o฀papo฀de฀loop฀
É฀muito฀fácil... E e a i (ou฀ laço)฀ se฀ encerra฀ no฀ comando฀ for?฀
f i ge ad el Ledo฀engano,฀amigo,฀vamos฀a฀partir฀de฀
$ ca c al h DOS R i e f i agora฀ver฀mais฀dois฀comandos.
! bi ba h bai ad
Sc i e a e e edag gic f al fei O฀��ma���฀while
c ja f çã é c a a Todos฀os฀programadores฀conhecem฀este฀
a idade de ala a de Agora฀ vamos฀ testar฀ o฀ programa฀ pas- comando,฀porque฀é฀comum฀a฀todas฀as฀
a i S e- e e a sando฀esse฀arquivo฀como฀parâmetro: linguagens.฀Nelas,฀o฀que฀normalmente฀
ala a e ã e a ada ocorre฀é฀que฀um฀bloco฀de฀comandos฀é฀
e e i e aç , <TAB> $ c al h A D DOS executado,฀ enquanto฀ (enquanto,฀ em฀
<ENTER> O a i A D DOS e 4 inglês,฀ é฀ “while”)฀ uma฀ determinada฀
if [ $ - e ] ala a condição฀for฀verdadeira.
he
ech : $ ca i h d U Funcionou฀ legal!฀ Tabela฀1:฀Expressões฀��฀Shell
a i Se฀ você฀ se฀ lembra,฀ Expressã� Resulta��
e i em฀ nossa฀ última฀ id++฀฀id-- pós-incremento฀e฀pós-decremento฀de฀variáveis
fi aula฀ mostramos฀ o฀ ++id฀฀--id pré-incremento฀e฀pré-decremento฀de฀variáveis
C = loop฀for฀a฀seguir: ** exponenciação
f Pala a i $ ca $ *฀฀/฀฀% multiplicação,฀divisão,฀resto฀da฀divisão฀(módulo)
d f i<= +฀฀- adição,฀subtração

C =$ C d <=฀฀>=฀฀<฀฀> comparação
==฀฀!= igualdade,฀desigualdade
d e le i
&& E฀lógico
ech O a i $ e $C U ech - $i
|| OU฀lógico
ala a d e

�����������������������������
86 edição฀06 [Link]฀
��������������������������������������������������������������������������������
����������������������������������������������������
�����������������������������������������������������������������������������������������������������������������������������������������������������
Papo฀de฀Botequim LINUX฀USER

Pois฀bem,฀isso฀é฀o฀que฀acontece฀nas฀ $ l ga e h $ca bg h
linguagens฀ caretas!฀ Em฀ programação฀ efe Ja 4 8:4 U ! bi ba h
Shell,฀o฀bloco฀de฀comandos฀é฀executado฀ 4 44 E ec a e i a
enquanto฀ um฀ comando฀ for฀ verdadeiro.฀ efe Ja 4 8:4 U ce e backg d
E฀ é฀ claro,฀ se฀ quiser฀ testar฀ uma฀ condi- 4 44 $ & C l ca e backg d
ção,฀use฀o฀comando฀while฀junto฀com฀o฀ hile | g e - $!
comando฀ test,฀ exatamente฀ como฀ você฀ efe Ja 4 8:4 U d
aprendeu฀a฀fazer฀no฀if,฀lembra?฀Então฀a฀ 4 44 lee 5
sintaxe฀do฀comando฀fi฀ca฀assim: d e
Isto฀é,฀a฀cada฀30฀segundos฀a฀saída฀do฀ ech Fi d P ce $
hile c a d comando฀grep฀seria฀enviada฀para฀a฀tela,฀
d o฀que฀não฀é฀legal,฀já฀que฀poluiria฀a฀tela฀ Esse฀script฀é฀bastante฀similar฀ao฀ante-
c d do฀meu฀micro฀e฀a฀mensagem฀tão฀espe- rior,฀mas฀tem฀uns฀macetes฀a฀mais,฀veja฀
c d rada฀poderia฀passar฀despercebida.฀Para฀ só:฀ele฀tem฀que฀ser฀executado฀em฀back-
evitar฀isso,฀já฀sabemos฀que฀a฀saída฀do฀ ground฀para฀não฀prender฀o฀prompt฀mas฀
c d pipeline฀tem฀que฀ser฀redirecionada฀para฀ o฀$!฀será฀o฀do฀programa฀passado฀como฀
d e o฀dispositivo฀/dev/null. parâmetro,฀ já฀ que฀ ele฀ foi฀ colocado฀ em฀
background฀ após฀ o฀ [Link]฀ propria-
e฀ dessa฀ forma,฀ o฀ bloco฀ formado฀ pelas฀ $ ca l ga e h mente฀dito.฀Repare฀também฀na฀opção฀-q฀
instruções฀cmd1,฀cmd2,...฀e฀cmdn฀é฀exe- ! bi ba h (quiet)฀do฀grep,฀que฀serve฀para฀fazê-lo฀
cutado฀enquanto฀a฀execução฀da฀instru- E e e a X a ã e ha “trabalhar฀em฀silêncio”.฀O฀mesmo฀resul-
ção฀comando฀for฀bem฀sucedida. c igh de efe e a : tado฀ poderia฀ ser฀ obtido฀ com฀ a฀ linha:฀
Suponha฀ a฀ seguinte฀ cena:฀ tinha฀ hile h | g e efe > de ll while฀ps฀|฀grep฀$!฀>฀/dev/null,฀como฀nos฀
uma฀ tremenda฀ gata฀ me฀ esperando฀ e฀ d exemplos฀que฀vimos฀até฀agora.
eu฀estava฀preso฀no฀trabalho฀sem฀poder฀ lee Vamos฀ melhorar฀ o฀ nosso฀ velho฀
sair฀porque฀o฀meu฀chefe,฀que฀é฀um฀pé฀ d e musinc,฀nosso฀programa฀para฀incluir฀
no฀saco฀(aliás฀chefe-chato฀é฀uma฀redun- ech O a e a d , ã U registros฀ no฀ arquivo฀ musicas,฀ mas฀
dância,฀né?),฀ainda฀estava฀na฀sala฀dele,฀ he i e, dê e i e á a l a antes฀ preciso฀ te฀ ensinar฀ a฀ pegar฀
que฀fi฀ca฀bem฀na฀minha฀passagem฀para฀a฀ um฀dado฀da฀tela,฀e฀já฀vou฀avisando:฀
rua.฀Ele฀começou฀a฀fi฀car฀cabreiro฀depois฀ Agora฀ quero฀ montar฀ um฀ script฀ que฀ só฀ vou฀ dar฀ uma฀ pequena฀ dica฀ do฀
da฀quinta฀vez฀que฀passei฀pela฀sua฀porta฀ receba฀ o฀ nome฀ (e฀ eventuais฀ parâme- comando฀ read฀ (que฀ é฀ quem฀ pega฀ o฀
e฀olhei฀para฀ver฀se฀já฀havia฀ido฀embora.฀ tros)฀de฀um฀programa฀que฀será฀execu- dado฀ da฀ tela),฀ que฀ seja฀ o฀ sufi฀ciente฀
Então฀voltei฀para฀a฀minha฀mesa฀e฀fi฀z,฀no฀ tado฀em฀background฀e฀que฀me฀informe฀ para฀ resolver฀ este฀ nosso฀ problema.฀
servidor,฀um฀script฀assim: do฀seu฀término.฀Mas,฀para฀você฀enten- Em฀uma฀outra฀rodada฀de฀chope฀vou฀
der฀ este฀ exemplo,฀ primeiro฀ tenho฀ de฀ te฀ ensinar฀ tudo฀ sobre฀ o฀ assunto,฀
$ ca l ga e h mostrar฀uma฀nova฀variável฀do฀sistema.฀ inclusive฀ como฀ formatar฀ tela,฀ mas฀
! bi ba h Veja฀estes฀comandos฀executados฀direta- hoje฀estamos฀falando฀sobre฀loops.฀A฀
E e e a X a ã e ha mente฀no฀prompt: sintaxe฀ do฀ comando฀ read฀ que฀ nos฀
c igh de efe e a : interessa฀por฀hoje฀é฀a฀seguinte:
hile h | g e efe $ lee &
d [ ] $ ead - de lei a a
lee $ ech $!
d e Onde฀ “prompt฀ de฀ leitura”฀ é฀ o฀ texto฀
ech O a e a d , ã U [ ] D e lee que฀ você฀ quer฀ que฀ apareça฀ escrito฀ na฀
he i e, dê e i e á à l a $ ech $! tela.฀Quando฀o฀operador฀teclar฀tal฀dado,฀
ele฀ será฀ armazenado฀ na฀ variável฀ var.฀
Neste฀ scriptzinho,฀ o฀ comando฀ while฀ Por฀exemplo:
testa฀o฀pipeline฀composto฀pelos฀coman- Isto฀ é,฀ criei฀ um฀ processo฀ em฀ back-
dos฀ who฀ e฀ grep,฀ que฀ será฀ verdadeiro฀ ground฀ que฀ dorme฀ por฀ 10฀ segundos,฀ $ ead - Tí l d Álb : Ti
enquanto฀ o฀ grep฀ localizar฀ a฀ palavra฀ somente฀para฀mostrar฀que฀a฀variável฀$!฀
xefe฀ na฀ saída฀ do฀ comando฀ who.฀ Desta฀ guarda฀o฀PID฀(Process฀ID)฀do฀último฀pro- Bem,฀uma฀vez฀entendido฀isso,฀vamos฀
forma,฀o฀script฀dormirá฀por฀30฀segundos฀ cesso฀ em฀ background.฀ Mas฀ observe฀ a฀ à฀ especificação฀ do฀ nosso฀ problema:฀
enquanto฀o฀chefe฀estiver฀logado฀(Argh!).฀ listagem฀e฀repare,฀após฀a฀linha฀do฀Done,฀ faremos฀um฀programa฀que฀inicialmente฀
Assim฀que฀ele฀se฀desconectar฀do฀servi- que฀ a฀ variável฀ reteve฀ o฀ valor฀ mesmo฀ lerá฀o฀nome฀do฀álbum฀e฀em฀seguida฀fará฀
dor,฀o฀fl฀uxo฀do฀script฀sairá฀do฀loop฀e฀te฀ após฀o฀término฀desse฀processo. um฀loop฀de฀leitura,฀pegando฀o฀nome฀da฀
mostrará฀ a฀ tão฀ ansiada฀ mensagem฀ de฀ Bem,฀sabendo฀isso,฀já฀fi฀ca฀mais฀fácil฀ música฀ e฀ o฀ artista.฀ Esse฀ loop฀ termina฀
liberdade.฀Mas฀quando฀executei฀o฀script,฀ monitorar฀ qualquer฀ processo฀ em฀ back- quando฀for฀informada฀uma฀música฀com฀
adivinha฀o฀que฀aconteceu? ground.฀Veja฀só฀como: nome฀vazio,฀isto฀é,฀quando฀o฀operador฀

�����������������������������
[Link]฀ edição฀06 87
��������������������������������������������������������������������������������
���������������������������������������������������
����������������������������������������������������������������������������������������������������������������������������������������������������
LINUX฀USER Papo฀de฀Botequim

Di�a il c a d $ca chegada h


Leitura฀de฀arquivo฀signifi฀ca฀ler฀um฀a฀um฀ d ! bi ba h
todos฀os฀registros,฀o฀que฀é฀sempre฀uma฀ c d il h | g e j li
operação฀lenta.฀Fique฀atento฀para฀não฀usar฀ c d d
o฀while฀quando฀for฀desnecessário.฀O฀Shell฀ lee
tem฀ferramentas฀como฀o฀sed฀e฀a฀família฀ c d d e
grep,฀que฀vasculham฀arquivos฀de฀forma฀ d e ech $ da e E d à U
otimizada฀sem฀que฀seja฀necessário฀o฀uso฀do฀ H: Mh > ela l g
while฀para฀fazê-lo฀registro฀a฀registro.
e฀dessa฀forma฀o฀bloco฀de฀comandos฀for-
mado฀pelas฀instruções฀cmd1,฀cmd2,...฀e฀ Olha฀que฀safado!฀O฀cara฀estava฀mon-
der฀um฀simples฀<ENTER>.฀Para฀facili- cmdn฀é฀executado฀até฀que฀a฀execução฀da฀ tando฀um฀log฀com฀os฀meus฀horários฀de฀
tar฀a฀vida฀do฀operador,฀vamos฀oferecer฀ instrução฀comando฀seja฀bem฀sucedida. chegada,฀ e฀ ainda฀ por฀ cima฀ chamou฀ o฀
como฀default฀o฀mesmo฀nome฀do฀artista฀ Como฀eu฀te฀disse,฀while฀e฀until฀funcio- arquivo฀de฀[Link]!฀O฀que฀será฀que฀
da฀música฀anterior฀(já฀que฀é฀normal฀que฀ nam฀de฀forma฀antagônica,฀e฀isso฀é฀muito฀ ele฀quis฀dizer฀com฀isso?
o฀álbum฀seja฀todo฀do฀mesmo฀artista)฀até฀ fácil฀ de฀ demonstrar:฀ em฀ uma฀ guerra,฀ Nesse฀ script,฀ o฀ pipeline฀ who฀ |฀ grep฀
que฀ele฀deseje฀alterá-lo.฀Veja฀na฀listagem฀ sempre฀ que฀ se฀ inventa฀ uma฀ arma,฀ o฀ julio,฀ será฀ bem฀ sucedido฀ somente฀
1฀como฀fi฀cou฀o฀programa. inimigo฀ busca฀ uma฀ solução฀ para฀ neu- quando฀ julio฀ for฀ encontrado฀ na฀ saída฀
Nosso฀ exemplo฀ começa฀ com฀ a฀ lei- tralizá-la.฀Foi฀baseado฀nesse฀principio฀ do฀ comando฀ who,฀ isto฀ é,฀ quando฀ eu฀
tura฀do฀título฀do฀álbum.฀Caso฀ele฀não฀ belicoso฀que฀meu฀chefe฀desenvolveu,฀no฀ me฀ “logar”฀ no฀ servidor.฀ Até฀ que฀ isso฀
seja฀ informado,฀ terminamos฀ a฀ execu- mesmo฀servidor฀em฀que฀eu฀executava฀o฀ aconteça,฀o฀comando฀sleep,฀que฀forma฀
ção฀do฀programa.฀Em฀seguida฀um฀grep฀ [Link],฀ um฀ script฀ para฀ controlar฀ o฀ o฀bloco฀de฀instruções฀do฀until,฀colocará฀
procura,฀no฀início฀(^)฀de฀cada฀registro฀ meu฀horário฀de฀chegada. o฀ programa฀ em฀ espera฀ por฀ 30฀ segun-
de฀músicas,฀o฀título฀informado฀seguido฀ Um฀dia฀tivemos฀um฀problema฀na฀rede.฀ dos.฀Quando฀esse฀loop฀encerrar-se,฀será฀
do฀separador฀(^)฀(que฀está฀precedido฀de฀ Ele฀me฀pediu฀para฀dar฀uma฀olhada฀no฀ enviada฀uma฀mensagem฀para฀o฀arquivo฀
uma฀contrabarra฀[\]฀para฀protegê-lo฀da฀ micro฀dele฀e฀me฀deixou฀sozinho฀na฀sala.฀ [Link].฀ Supondo฀ que฀ no฀ dia฀ 20/01฀
interpretação฀do฀Shell). Resolvi฀bisbilhotar฀os฀arquivos฀–฀guerra฀ eu฀me฀“loguei”฀às฀11:23฀horas,฀a฀mensa-
Para฀ ler฀ os฀ nomes฀ dos฀ artistas฀ e฀ as฀ é฀guerra฀–฀e฀veja฀só฀o฀que฀descobri: gem฀seria฀a฀seguinte:
músicas฀do฀álbum,฀foi฀montado฀um฀loop฀
while฀simples,฀cujo฀único฀destaque฀é฀o฀ Listagem฀1
fato฀de฀ele฀armazenar฀o฀nome฀do฀intér-
$ ca i c h
prete฀ da฀ música฀ anterior฀ na฀ variável฀
! bi ba h
$oArt,฀que฀só฀terá฀o฀seu฀conteúdo฀alte-
Cada a CD e a 4
rado฀quando฀algum฀dado฀for฀informado฀
para฀a฀variável฀$Art,฀isto฀é,฀quando฀não฀
clea
for฀ teclado฀ um฀ simples฀ ENTER฀ para฀
ead - Tí l d Álb : Ti
manter฀o฀artista฀anterior.
[ $Ti ] || e i Fi da e ec çã e í l a i
O฀que฀foi฀visto฀até฀agora฀sobre฀o฀while฀
if g e ^$Ti \^ ica > de ll
foi฀muito฀pouco.฀Esse฀comando฀é฀muito฀
he
utilizado,฀ principalmente฀ para฀ leitura฀
ech E e álb já e á cada ad
de฀ arquivos,฀ porém฀ ainda฀ nos฀ falta฀
e i
bagagem฀ para฀ prosseguir.฀ Depois฀ que฀

aprendermos฀mais฀sobre฀isso,฀veremos฀
Reg= $Ti ^
essa฀instrução฀mais฀a฀fundo.
C =

O฀��ma���฀until A =
hile e
Este฀ comando฀ funciona฀ de฀ forma฀
d
idêntica฀ ao฀ while,฀ porém฀ ao฀ contrário.฀
ech Dad da ilha $C :
Disse฀ tudo฀ mas฀ não฀ disse฀ nada,฀ né?฀ É฀
ead - M ica: M
o฀ seguinte:฀ ambos฀ testam฀ comandos;฀
[ $M ] || b eak Sai e a i
ambos฀ possuem฀ a฀ mesma฀ sintaxe฀ e฀
ead - A i a: $ A A
ambos฀atuam฀em฀loop;฀porém,฀o฀while฀
[ $A ] && A = $A Se a i A a e i
executa฀o฀bloco฀de฀instruções฀do฀loop฀
Reg= $Reg$ A ~$M : M a d egi
enquanto฀ um฀ comando฀ for฀ bem฀ suce-
C =$ C
dido;฀já฀o฀until฀executa฀o฀bloco฀do฀loop฀
A li ha a e i b de ia e C
até฀que฀o฀comando฀seja฀bem฀sucedido.฀
d e
Parece฀pouca฀coisa,฀mas฀a฀diferença฀é฀
ech $Reg >> ica
fundamental.฀A฀sintaxe฀do฀comando฀é฀
ica - ica
praticamente฀a฀mesma฀do฀while.฀Veja:

�����������������������������
88 edição฀06 [Link]฀
��������������������������������������������������������������������������������
����������������������������������������������������
�����������������������������������������������������������������������������������������������������������������������������������������������������
Papo฀de฀Botequim LINUX฀USER

E à : h
Atalh�s฀��฀
l��p �� ��

Voltando฀ à฀ nossa฀ CDteca,฀ quando฀ Nem฀ sempre฀ um฀ �������� ��������


vamos฀ cadastrar฀ músicas฀ seria฀ ideal฀ ciclo฀ de฀ programa,฀
que฀ pudéssemos฀ cadastrar฀ diversos฀ c o m p r e e n d i d o฀
CDs฀ de฀ uma฀ vez฀ só.฀ Na฀ última฀ versão฀ entre฀ um฀ do฀ e฀ um฀ ����� ����� ����� ��������
do฀programa฀isso฀não฀ocorre:฀a฀cada฀CD฀ done,฀sai฀pela฀porta฀
cadastrado฀o฀programa฀termina.฀Veja฀na฀ da฀ frente.฀ Em฀ algu-
�������� ��������
listagem฀2฀como฀melhorá-lo. mas฀oportunidades,฀
Nesta฀versão,฀um฀loop฀maior฀foi฀adi- temos฀ que฀ colocar฀
���� ����
cionado฀antes฀da฀leitura฀do฀título,฀que฀ um฀ comando฀ que฀
só฀ terminará฀ quando฀ a฀ variável฀ $Para฀ aborte฀ de฀ forma฀
c ont rolada฀ esse฀ �s�฀��฀��ma���฀�����
deixar฀ de฀ ser฀ vazia.฀ Caso฀ o฀ título฀ do฀ �s�฀��฀��ma���฀��������
álbum฀ não฀ seja฀ informado,฀ a฀ variá- loop.฀ De฀ maneira฀ Figura฀1:฀A฀estrutura฀��s฀��ma���s฀break฀e฀continue,฀usa��s฀para฀���tr�-
vel฀$Para฀receberá฀um฀valor฀(coloquei฀ inversa,฀ algumas฀ lar฀�฀fl฀ux�฀�e฀exe�uçã�฀em฀l��ps.
1,฀ mas฀ poderia฀ ter฀ colocado฀ qualquer฀ vezes฀ deseja mos฀
coisa)฀para฀sair฀desse฀loop,฀terminando฀ que฀ o฀ f lu xo฀ de฀ pectivamente฀os฀comandos฀break฀(que฀
o฀programa.฀No฀resto,฀o฀script฀é฀idêntico฀ execução฀ do฀ programa฀ volte฀ antes฀ de฀ já฀vimos฀rapidamente฀nos฀exemplos฀do฀
à฀versão฀anterior. chegar฀ ao฀ done.฀ Para฀ isso,฀ temos฀ res- comando฀while)฀e฀continue,฀que฀funcio-
nam฀da฀forma฀mostrada฀na฀fi฀gura฀1.฀
Listagem฀2 O฀ que฀ eu฀ não฀ havia฀ dito฀ anterior-
mente฀é฀que฀nas฀suas฀sintaxes฀genéricas฀
$ ca i c h
eles฀aparecem฀da฀seguinte฀forma:
! bi ba h
Cada a CD e a 5
b eak [ d l ]

Pa a=
e฀também:
il [ $Pa a ]
d
c i e [ d l ]
clea
ead - Tí l d Álb : Ti
Onde฀ qtd฀ loop฀ representa฀ a฀ quanti-
if [ ! $Ti ] Se i l a i
dade฀dos฀loops฀mais฀internos฀sobre฀os฀
he
quais฀os฀comandos฀irão฀atuar.฀Seu฀valor฀
Pa a= Lig ei flag de aída
por฀default฀é฀1.
el e
Duvido฀ que฀ você฀ nunca฀ tenha฀ apa-
if g e ^$Ti \^ ica > de ll
gado฀ um฀ arquivo฀ e฀ logo฀ após฀ deu฀ um฀
he
tabefe฀ na฀ testa฀ se฀ xingando฀ porque฀
ech E e álb já e á cada ad
não฀ devia฀ tê-lo฀ removido.฀ Pois฀ é,฀ na฀
e i
décima฀vez฀que฀fi฀z฀esta฀besteira,฀criei฀

um฀ script฀ para฀ simular฀ uma฀ lixeira,฀
Reg= $Ti ^
isto฀é,฀quando฀mando฀remover฀um฀(ou฀
C =
vários)฀ arquivo(s),฀ o฀ programa฀ “fi฀nge”฀
A =
que฀deletou,฀mas฀no฀duro฀o฀que฀ele฀fez฀
hile [ $Ti ]
foi฀mandá-lo(s)฀para฀o฀diretório฀/tmp/
d
LoginName_do_usuario.฀ Chamei฀ esse฀
ech Dad da ilha $C :
programa฀de฀erreeme฀e฀no฀arquivo฀/etc/
ead - M ica: M
profi฀le฀ coloquei฀ a฀ seguinte฀ linha,฀ que฀
[ $M ] || b eak Sai e a i
cria฀um฀“apelido”฀para฀ele:
ead - A i a: $ A A
[ $A ] && A = $A Se a i A a e i
alia =e ee e
Reg= $Reg$ A ~$M : M a d egi
C =$ C
Veja฀o฀programa฀na฀listagem฀3.฀Como฀
A li ha a e i b de ia e C
você฀pode฀ver,฀a฀maior฀parte฀do฀script฀
d e
é฀ formada฀ por฀ pequenas฀ críticas฀ aos฀
ech $Reg >> ica
parâmetros฀ informados,฀ mas฀ como฀ o฀
ica - ica
script฀pode฀ter฀recebido฀diversos฀arqui-

vos฀a฀remover,฀a฀cada฀arquivo฀que฀não฀
d e
se฀ encaixa฀ dentro฀ do฀ especifi฀cado฀ há฀

�����������������������������
[Link]฀ edição฀06 89
��������������������������������������������������������������������������������
���������������������������������������������������
����������������������������������������������������������������������������������������������������������������������������������������������������
LINUX฀USER Papo฀de฀Botequim

Listagem฀3:฀[Link]
$ ca e ee e h he
! bi ba h ech $A a e i e
E =
Sal a d c ia de a i a e de e ê-l c i e V l a a a c a d f

Te de e ai a i a e e
if [ $ -e ] C d di a e i f a e d di de $A
he Di O ig=`di a e $A `
ech E -> U : e ee e a [a ] [a ] Ve ifica e i ã de g a aca di e i
ech O de e aca ac e e e e i id E U if [ ! - $Di O ig ]
e ee e a * he
e i ech Se e i ã di e i de $A
fi E =4
c i e V l a a a c a d f
Va iá el d i e a e c é e d á i fi
Me Di = $LOGNAME
Se ã e i i e di e i b Se e e a ia d a li ei a
if [ ! -d $Me Di ] if [ $Di O ig = $Me Di ]
he he
kdi $Me Di V c iá-l ech $A fica a e c ia de eg a ca
fi -i $A Pe g a a e de e e
Se á e á i e e
Se ã g a a di e i [ -f $A ] || ech $A i e id
if [ ! - $Me Di ] c i e
he fi
ech I i el al a a i e $Me Di U
M de a e i e G a d fi d a i e di e i igi alU
e i a a á-l e c i de dele e
fi cd $Di O ig
d >> $A
Va iá el e i dica c d de e d g a a $A $Me Di Sal e e
E = ech $A e id
U f e i ecebe a a e a ad d e
f A
d Pa e e al e d e a a c dig
Se e e a i ã e i i de e
if [ ! -f $A ] e i $E

um฀continue,฀para฀que฀a฀seqüência฀volte฀ faça-o฀ em฀ casa฀ e฀ me฀ traga฀ para฀ dis- um฀ email฀ para฀ [Link]@gmail.
para฀ o฀ loop฀ do฀ for฀ de฀ forma฀ a฀ receber฀ cutirmos฀no฀nosso฀próximo฀encontro฀ com.฀Agora฀chega฀de฀papo฀que฀eu฀já฀
outros฀arquivos.฀ aqui฀no฀boteco. estou฀de฀goela฀seca฀de฀tanto฀falar.฀Me฀
Quando฀você฀está฀no฀Windows฀(com฀ –฀ ฀Poxa,฀mas฀nesse฀eu฀acho฀que฀vou฀dan- acompanha฀no฀próximo฀chope฀ou฀já฀
perdão฀da฀má฀palavra)฀e฀tenta฀remover฀ çar,฀pois฀não฀sei฀nem฀como฀começar... vai฀sair฀correndo฀para฀fazer฀o฀script฀
aquele฀monte฀de฀lixo฀com฀nomes฀esqui- –฀ ฀C ara,฀ este฀ programa฀ é฀ como฀ tudo฀ que฀passei?฀
sitos฀ como฀ [Link],฀ se฀ der฀ erro฀ o฀ que฀ se฀ faz฀ em฀ Shell:฀ extrema- –฀ ฀Deixa฀eu฀pensar฀um฀pouco...
em฀um฀dos฀arquivos฀os฀outros฀não฀são฀ mente฀ fácil.฀ É฀ para฀ ser฀ feito฀ em,฀ no฀ –฀ ฀Chico,฀traz฀mais฀um฀chope฀enquanto฀
removidos,฀não฀é?฀Então,฀o฀continue฀foi฀ máximo,฀ 10฀ linhas.฀ Não฀ se฀ esqueça฀ ele฀pensa!฀
usado฀ para฀ evitar฀ que฀ uma฀ improprie- de฀que฀o฀arquivo฀está฀salvo฀em฀/tmp/
dade฀dessas฀ocorra,฀isto฀é,฀mesmo฀que฀ $LOGNAME฀e฀que฀sua฀última฀linha฀é฀ Julio฀Cezar฀Neves฀é฀Analista฀de฀
SOBRE฀O฀AUTOR

dê฀ erro฀ na฀ remoção฀ de฀ um฀ arquivo,฀ o฀ o฀ diretório฀ em฀ que฀ ele฀ residia฀ antes฀ Suporte฀de฀Sistemas฀desde฀1969฀e฀tra-
programa฀ continuará฀ removendo฀ os฀ de฀ ser฀ “removido”.฀ Também฀ não฀ se฀ balha฀com฀Unix฀desde฀1980,฀quando฀
outros฀que฀foram฀passados. esqueça฀ de฀ criticar฀ se฀ foi฀ passado฀ o฀ participou฀do฀desenvolvimento฀do฀
–฀ ฀Eu฀ acho฀ que฀ a฀ esta฀ altura฀ você฀ deve฀ nome฀do฀arquivo฀a฀ser฀removido. SOX,฀um฀sistema฀operacional฀similar฀
estar฀ curioso฀ para฀ ver฀ o฀ programa฀ –฀ ฀É฀eu฀vou฀tentar,฀mas฀sei฀não... ao฀Unix฀produzido฀pela฀Cobra฀Com-
putadores.฀Pode฀ser฀contatado฀no฀
que฀restaura฀o฀arquivo฀removido,฀não฀ –฀ ฀Tenha฀fé,฀irmão,฀eu฀tô฀te฀falando฀que฀
e-mail฀[Link]@[Link]
é?฀ Pois฀ então฀ aí฀ vai฀ vai฀ um฀ desafi฀o:฀ é฀mole!฀Qualquer฀dúvida฀é฀só฀passar฀

�����������������������������
90 edição฀06 [Link]฀
��������������������������������������������������������������������������������
Linux฀User Papo฀de฀botequim

Papo฀de฀Botequim
Curso de Shell Script

Parte฀VII

Dave Hamilton - [Link]


De pouco adianta ter acesso à informação se ela não puder ser apresentada
de forma atraente e que facilite a compreensão. O comando tput pode ser
usado por shell scripts para posicionar caracteres e criar todos os tipos de
efeito com o texto mostrado na tela. Garçom, solta uma geladinha!
por฀Julio฀Cezar฀Neves

C
umequié,฀rapaz!฀Derreteu฀os฀pen- –฀฀Peraí,฀deixa฀eu฀ver฀se฀entendi฀o฀que฀você฀ –฀฀É,฀tô฀vendo฀que฀o฀bichinho฀do฀shell฀te฀
samentos฀para฀fazer฀o฀scriptzinho฀ fez:฀você฀coloca฀na฀variável฀Di ฀a฀última฀ pegou.฀Vamos฀ver฀como฀ler฀dados,฀mas฀
que฀eu฀te฀pedi? linha฀do฀arquivo฀a฀ser฀restaurado,฀em฀ antes฀vou฀te฀mostrar฀um฀comando฀que฀
–฀฀É ,฀eu฀realmente฀tive฀de฀colocar฀muita฀ nosso฀caso฀ $LOGNAME $ ฀(onde฀ te฀dá฀todas฀as฀ferramentas฀para฀formatar฀
pensação฀na฀tela฀preta,฀mas฀acho฀que฀ $LOGNAME฀é฀o฀nome฀do฀usuário฀logado,฀ uma฀tela฀de฀entrada฀de฀dados.
fi฀nalmente฀consegui!฀Bem,฀pelo฀menos฀ e฀ $ ฀é฀o฀primeiro฀parâmetro฀que฀você฀
nos฀testes฀que฀fi฀z฀a฀coisa฀funcionou,฀ passou฀ao฀script),฀já฀que฀foi฀lá฀que฀arma- O comando tput
mas฀você฀tem฀sempre฀que฀botar฀chifres฀ zenamos฀o฀nome฀e฀caminho฀originais฀do฀ O฀principal฀uso฀desse฀comando฀é฀o฀posi-
em฀cabeça฀de฀cachorro! arquivo฀antes฀de฀movê-lo฀para฀o฀diretório฀ cionamento฀do฀cursor฀na฀tela.฀Alguns฀
–฀฀Não฀é฀bem฀assim.฀É฀que฀programar฀em฀ (defi฀nido฀na฀variável฀Di ).฀O฀comando฀ parâmetros฀podem฀não฀funcionar฀se฀o฀
Shell฀Script฀é฀muito฀fácil,฀mas฀o฀que฀é฀ g e - ฀apaga฀essa฀linha,฀restaurando฀ modelo฀de฀terminal฀defi฀nido฀pela฀vari-
realmente฀importante฀são฀as฀dicas฀e฀ o฀arquivo฀ao฀estado฀original,฀e฀o฀manda฀ ável฀de฀ambiente฀$TERM฀não฀suportá-los.฀
macetes฀que฀não฀são฀triviais.฀As฀cor- de฀volta฀pra฀onde฀ele฀veio.฀A฀última฀linha฀ A฀tabela 1฀apresenta฀apenas฀os฀principais฀
reções฀que฀faço฀são฀justamente฀para฀ o฀apaga฀da฀“lixeira”.฀Sensacional!฀Impe- parâmetros฀e฀os฀efeitos฀resultantes,฀mas฀
mostrá-los.฀Mas฀vamos฀pedir฀dois฀cho- cável!฀Nenhum฀erro!฀Viu?฀Você฀já฀está฀ existem฀muito฀mais฀deles.฀Para฀saber฀tudo฀
pes฀enquanto฀dou฀uma฀olhadela฀no฀teu฀ pegando฀as฀manhas฀do฀shell! sobre฀o฀tput,฀veja฀a฀referência฀[1].฀
script฀lá฀na฀listagem 1.฀Aê฀Chico,฀traz฀ –฀฀E ntão฀vamos฀lá,฀chega฀de฀lesco-lesco฀ Vamos฀fazer฀um฀programa฀bem฀besta฀
dois฀chopes!฀E฀não฀se฀esqueça฀que฀um฀ e฀blá-blá-blá,฀sobre฀o฀quê฀nós฀vamos฀ e฀fácil฀para฀ilustrar฀melhor฀o฀uso฀desse฀
deles฀é฀sem฀colarinho! falar฀hoje? comando.฀É฀uma฀versão฀do฀famigerado฀
“Alô฀Mundo”,฀só฀que฀dessa฀vez฀a฀frase฀
Listagem 1 – [Link] será฀escrita฀no฀centro฀da฀tela฀e฀em฀vídeo฀
reverso.฀Depois฀disso,฀o฀cursor฀voltará฀para฀
! bi ba h
a฀posição฀original.฀Veja฀a฀listagem 2.
Como฀o฀programa฀já฀está฀todo฀comen-
Re a a a i dele ad ia e ee e
tado,฀acho฀que฀a฀única฀linha฀que฀precisa฀de฀
4
explicação฀é฀a฀8,฀onde฀criamos฀a฀variável฀
5
C l a.฀O฀estranho฀ali฀é฀aquele฀número฀
if [ $ -e ]
9,฀que฀na฀verdade฀indica฀o฀tamanho฀da฀
he
cadeia฀de฀caracteres฀que฀vou฀escrever฀na฀
8 ech U : $ <N e d a i a e e a ad >
tela.฀Dessa฀forma,฀este฀programa฀somente฀
e i
conseguiria฀centralizar฀cadeias฀de฀9฀carac-
fi
teres,฀mas฀veja฀isto:
Pega e d a i di e i igi al a l i a li ha
Di = ail - $LOGNAME $
$ a =Pa
O g e - e cl i a l i a li ha e ec ia a i c di e i
$ ech ${ a }
4 e e igi al e e ad
4
5 g e - $Di $LOGNAME $ > $Di $
$ a = Pa de B e i
Re e a i e já e a a ib d
$ ech ${ a }
$LOGNAME $

86 abril฀2005฀ edição฀07
[Link]
Linux฀User Papo฀de฀botequim

Tabela 1: Parâmetros do tput e฀a฀linha฀12฀(ech $ )฀passaria฀a฀ser:

Parâmetro Efeito ech $*


c li c l CUrsor Position – Posiciona o cursor na linha lin e coluna col. A origem (0,0) fica no
canto superior esquerdo da tela. Lendo dados da tela
b ld Coloca a tela em modo negrito Bem,฀a฀partir฀de฀agora฀vamos฀aprender฀
e Coloca a tela em modo de vídeo reverso tudo฀sobre฀leitura.฀Só฀não฀posso฀ensinar฀
a฀ler฀cartas฀e฀búzios฀porque฀se฀soubesse฀
Idêntico ao anterior
estaria฀rico,฀num฀pub฀Londrino฀tomando฀
l Sublinha os caracteres um฀scotch฀e฀não฀em฀um฀boteco฀tomando฀
bli k Deixa os caracteres piscando chope.฀Mas฀vamos฀em฀frente.
g Restaura a tela a seu modo normal Da฀última฀vez฀em฀que฀nos฀encontramos฀
e e Limpa o terminal e restaura suas definições de acordo com terminfo, ou seja, o ter- eu฀dei฀uma฀palhinha฀sobre฀o฀comando฀
minal volta ao comportamento padrão definido pela variável de ambiente $TERM ead.฀Antes฀de฀entrarmos฀em฀detalhes,฀
veja฀só฀isso:
li e Informa a quantidade de linhas que compõem a tela
c l Informa a quantidade de colunas que compõem a tela $ ead a a a
el Erase Line – Apaga a linha a partir da posição do cursor Pa de B e i
ed Erase Display – Apaga a tela a partir da posição do cursor $ ech $ a
Pa
il Insert Lines – Insere n linhas a partir da posição do cursor
$ ech $ a
dl Delete Lines – Remove n linhas a partir da posição do cursor
de
dch Delete CHaracters – Apaga n caracteres a partir da posição do cursor $ ech $ a
c Save Cursor position – Salva a posição do cursor B e i
c Restore Cursor position – Coloca o cursor na posição marcada pelo último c $ ead a a
Pa de B e i
$ ech $ a
Ahhh,฀melhorou!฀Então฀agora฀sabemos฀ essa฀construção฀devolve฀o฀número฀de฀ Pa
que฀a฀construção฀${ a ia el}฀devolve฀ caracteres฀do฀primeiro฀parâmetro฀pas- $ ech $ a
a฀quantidade฀de฀caracteres฀da฀variável.฀ sado฀para฀o฀programa.฀Se฀o฀parâmetro฀ de B e i
Assim฀sendo,฀vamos฀otimizar฀o฀nosso฀ tivesse฀espaços฀em฀branco,฀seria฀preciso฀
programa฀para฀que฀ele฀escreva฀em฀vídeo฀ colocá-lo฀entre฀aspas,฀senão฀o฀ $ ฀leva- Como฀você฀viu,฀o฀read฀recebe฀uma฀
reverso,฀no฀centro฀da฀tela฀(e฀indepen- ria฀em฀conta฀somente฀o฀pedaço฀antes฀ lista฀de฀parâmetros฀separada฀por฀espa-
dente฀do฀número฀de฀caracteres)฀a฀cadeia฀ do฀primeiro฀espaço.฀Para฀evitar฀este฀ ços฀em฀branco฀e฀coloca฀cada฀item฀dessa฀
de฀caracteres฀passada฀como฀parâmetro฀e฀ aborrecimento,฀é฀só฀substituir฀o฀$ ฀por฀ lista฀em฀uma฀variável.฀Se฀a฀quantidade฀
depois฀retorne฀o฀cursor฀à฀posição฀em฀que฀ $*,฀que฀como฀sabemos฀é฀o฀conjunto฀de฀ de฀variáveis฀for฀menor฀que฀a฀quantidade฀
estava฀antes฀da฀execução฀do฀script.฀Veja฀ todos฀os฀parâmetros.฀Então฀a฀linha฀8฀ de฀itens,฀a฀última฀variável฀recebe฀o฀res-
o฀resultado฀na฀listagem 3. ficaria฀assim: tante฀deles.฀Eu฀disse฀lista฀separada฀por฀
Este฀script฀é฀igual฀ao฀anterior,฀só฀que฀ espaços฀em฀branco,฀mas฀agora฀que฀você฀
trocamos฀o฀valor฀fixo฀na฀variável฀Coluna฀ Ce ali a d a e age a ela já฀conhece฀tudo฀sobre฀o฀$IFS฀(Inter฀Field฀
(9)฀por฀${ },฀onde฀esse฀ ฀é฀$ ,฀ou฀seja,฀ C l a=`$ C l a - ${ *} ` Separator฀–฀Separador฀entre฀campos),฀que฀

Listagem 2: [Link] Listagem 3: [Link] melhorado


! bi ba h ! bi ba h
Sc i b b a a e a Sc i b b a a e a
c a d e a c a d e ã
4 4
5 C l a =` c l ` Sal a a a idade de c l a a ela 5 C l a =` c l ` Sal a a a idade de c l a a ela
Li ha =` li e ` Sal a a a idade li ha a ela Li ha =` li e ` Sal a a a idade de li ha a ela
Li ha=$ Li ha Q al é a li ha ce al da ela Li ha=$ Li ha Q al é a li ha ce al da ela
8 C l a=$ C l a - Ce ali a a e age a ela 8 C l a=$ C l a - ${ } Ce ali a a e age a ela
c Sal a a içã d c c Sal a a ica d c
c $Li ha $C l a P ici a c a e de e c e e c $Li ha $C l a P ici a c a e de e c e e
e Víde e e e Vide e e
ech Al M d ech $
g Re a a íde a al g Re a a íde a al
4 c Re a a c à içã igi al 4 c De l e c à içã igi al

88 abril฀2005฀ edição฀07
[Link]
Papo฀de฀botequim฀ Linux฀User

eu฀te฀apresentei฀quando฀falávamos฀do฀ para฀que฀o฀\ ฀fosse฀entendido฀como฀ $ ead - - Digi e e e c le : U


comando฀ f ,฀será฀que฀ainda฀acredita฀ uma฀quebra฀de฀linha฀(new฀line)฀e฀não฀ N || ech Ei a le a!
nisso?฀Vamos฀testar: como฀um฀literal.฀Sob฀o฀Bash฀exis- Digi e e e c le : Ei a le a!
tem฀diversas฀opções฀do฀ ead฀que฀ser- $ ech $N
$ IFS= $IFS vem฀para฀facilitar฀a฀sua฀vida.฀Veja฀
$ IFS=: a฀tabela 2. O฀exemplo฀acima฀foi฀uma฀brincadeira,฀
$ ead a a a E฀agora฀direto฀aos฀exemplos฀curtos฀ pois฀eu฀só฀tinha฀2฀segundos฀para฀digitar฀o฀
Pa de B e i para฀demonstrar฀estas฀opções.฀Para฀ler฀ meu฀nome฀completo฀e฀mal฀tive฀tempo฀de฀
$ ech $ a um฀campo฀“Matrícula”: teclar฀um฀J฀(aquele฀colado฀no฀Eita),฀mas฀
Pa de B e i ele฀serviu฀para฀mostrar฀duas฀coisas:
$ ech $ a - ã al a li ha P฀1)฀O฀comando฀após฀o฀par฀de฀barras฀verti-
$ ech $ a $ ech - Ma ic la: ead Ma cais฀(o฀ou฀–฀or฀–฀lógico,฀lembra-se?)฀será฀
$ ead a a a Ma ic la: 45 executado฀caso฀a฀digitação฀não฀tenha฀
Pa :de:B e i $ ech $Ma sido฀concluída฀no฀tempo฀estipulado;
$ ech $ a 45 P฀2)฀A฀variável฀N ฀permaneceu฀vazia.฀Ela฀
Pa só฀receberá฀um฀valor฀quando฀o฀ENTER฀
$ ech $ a Podemos฀simplificar฀as฀coisas฀usando฀ for฀teclado.
de a฀opção฀- :
$ ech $ a $ ead - Se ha:
B e i $ ead - Ma ic la: Ma Se ha: $ ech $REPLY
$ IFS= $ IFS Ma ic la: 45 eg ed :
$ ech $Ma
Viu?฀eu฀estava฀furado!฀O฀ ead฀lê฀uma฀ 45 Aproveitei฀um฀erro฀no฀exemplo฀ante-
lista,฀assim฀como฀o฀ f ,฀separada฀pelos฀ rior฀para฀mostrar฀um฀macete.฀Quando฀
caracteres฀da฀variável฀ $IFS.฀Veja฀como฀ E฀podemos฀ler฀apenas฀uma฀quantidade฀ escrevi฀a฀primeira฀linha,฀esqueci฀de฀colo-
isso฀pode฀facilitar฀a฀sua฀vida: pré-determinada฀de฀caracteres: car฀o฀nome฀da฀variável฀que฀iria฀receber฀a฀
senha฀e฀só฀notei฀isso฀quando฀ia฀escrevê-
$ g e j li e c a d $ ead - 5 - CEP: N ead - U la.฀Felizmente฀a฀variável฀$REPLY฀do฀Bash฀
j li : :5 :544:J li C Ne e - :U - - C l contém฀a฀última฀seqüência฀de฀caracteres฀
h e j li : bi ba h CEP: 45- 8$ digitada฀–฀e฀me฀aproveitei฀disso฀para฀não฀
$ IFS= $IFS Sal a IFS a ig $ ech $N perder฀a฀viagem.฀Teste฀você฀mesmo฀o฀que฀
$ IFS=: 45 acabei฀de฀fazer.
$ g e j li e c a d | ead l a e U $ ech $C l O฀exemplo฀que฀dei,฀na฀verdade,฀era฀para฀
li id gid c e h e hell 8 mostrar฀que฀a฀opção฀- ฀impede฀que฀o฀que฀
$ ech -e $l a e\ $ id\ $gid\ $c e U está฀sendo฀digitado฀seja฀mostrado฀na฀tela.฀
\ $h e\ $ hell No฀exemplo฀acima฀executamos฀duas฀ Como฀no฀exemplo฀anterior,฀a฀falta฀do฀new฀
j li vezes฀o฀comando฀ ead:฀um฀para฀a฀pri- line฀fez฀com฀que฀o฀prompt฀de฀comando฀
5 meira฀parte฀do฀CEP฀e฀outra฀para฀o฀seu฀ ($)฀permanecesse฀na฀mesma฀linha.
544 complemento,฀deste฀modo฀formatando฀ Agora฀que฀sabemos฀ler฀da฀tela,฀vejamos฀
J li C Ne e - a฀entrada฀de฀dados.฀O฀cifrão฀($)฀logo฀ como฀se฀lêem฀os฀dados฀dos฀arquivos.
h e j li após฀o฀último฀algarismo฀digitado฀é฀
bi ba h necessário฀porque฀o฀ ead฀não฀inclui฀ Lendo arquivos
$ IFS= $ IFS Re a a IFS por฀ padrão฀ um฀ caractere฀ new฀ line฀ Como฀eu฀já฀havia฀lhe฀dito,฀e฀você฀deve฀se฀
implícito,฀como฀o฀echo. lembrar,฀o฀ hile฀testa฀um฀comando฀e฀exe-
Como฀você฀viu,฀a฀saída฀do฀g e ฀foi฀ Para฀ler฀só฀durante฀um฀determinado฀ cuta฀um฀bloco฀de฀instruções฀enquanto฀esse฀
redirecionada฀para฀o฀comando฀ ead,฀ limite฀de฀tempo฀(também฀conhecido฀ comando฀for฀bem฀sucedido.฀Ora,฀quando฀
que฀leu฀todos฀os฀campos฀de฀uma฀só฀ como฀time฀out): você฀está฀lendo฀um฀arquivo฀para฀o฀qual฀
tacada.฀A฀opção฀-e฀do฀ech ฀foi฀usada฀ você฀tem฀permissão฀de฀leitura,฀o฀ ead฀só฀
será฀mal฀sucedido฀quando฀alcançar฀o฀EOF฀
Tabela 2: Opções do read (End฀Of฀File฀–฀Fim฀do฀Arquivo).฀Portanto,฀
podemos฀ler฀um฀arquivo฀de฀duas฀maneiras.฀
Opção Ação A฀primeira฀é฀redirecionando฀a฀entrada฀do฀
- Escreve “prompt” na tela antes de fazer a leitura arquivo฀para฀o฀bloco฀ hile,฀assim:
- Lê até caracteres
hile ead Li ha
- eg Espera eg segundos para que a leitura seja concluída d
- Não exibe na tela os caracteres digitados. ech $Li ha
d e < a i

abril฀2005฀ edição฀07 89
[Link]
Linux฀User Papo฀de฀botequim

A฀segunda฀é฀redirecionando฀a฀saída฀ Como฀você฀viu,฀o฀script฀lista฀suas฀pró- que฀vou฀mostrar฀com฀um฀exemplo฀prático.฀


de฀um฀ ca ฀para฀o฀ hile,฀da฀seguinte฀ prias฀linhas฀com฀um฀sinal฀de฀menos฀(-)฀ Suponha฀que฀você฀queira฀listar฀um฀arquivo฀
maneira: antes฀e฀outro฀depois฀de฀cada฀uma฀e,฀no฀ e฀quer฀que฀a฀cada฀dez฀registros฀essa฀listagem฀
final,฀exibe฀o฀conteúdo฀da฀variável฀$Ul i .฀ pare฀para฀que฀o฀operador฀possa฀ler฀o฀con-
ca a i | Repare,฀no฀entanto,฀que฀o฀conteúdo฀dessa฀ teúdo฀da฀tela,฀e฀que฀ela฀só฀continue฀depois฀
hile ead Li ha variável฀permanece฀vazio.฀Ué,฀será฀que฀ de฀o฀operador฀pressionar฀qualquer฀tecla.฀
d a฀variável฀não฀foi฀atualizada?฀Foi,฀e฀isso฀ Para฀não฀gastar฀papel฀(da฀Linux฀Magazine),฀
ech $Li ha pode฀ser฀comprovado฀porque฀a฀linha฀ech vou฀fazer฀essa฀listagem฀na฀horizontal.฀Meu฀
d e -$Ul i - ฀lista฀corretamente฀as฀linhas.฀ arquivo฀( e )฀tem฀30฀registros฀com฀
Então฀por฀que฀isso฀aconteceu? números฀seqüenciais.฀Veja:
Cada฀um฀dos฀processos฀tem฀suas฀van- Como฀eu฀disse,฀o฀bloco฀de฀instruções฀
tagens฀e฀desvantagens.฀O฀primeiro฀é฀mais฀ redirecionado฀pelo฀pipe฀(|)฀é฀executado฀ $ e > e
rápido฀e฀não฀necessita฀de฀um฀subshell฀ em฀um฀subshell฀e,฀lá,฀as฀variáveis฀são฀ $ ca ag h
para฀assisti-lo฀mas,฀em฀contrapartida,฀o฀ atualizadas.฀Quando฀esse฀subshell฀ter- ! bi ba h
redirecionamento฀fica฀pouco฀visível฀em฀ mina,฀as฀atualizações฀das฀variáveis฀vão฀ P g a a de e e a a e c e e
um฀bloco฀de฀instruções฀grande,฀o฀que฀ para฀as฀profundezas฀do฀inferno฀junto฀com฀ li ha e a a a a le
por฀vezes฀prejudica฀a฀visualização฀do฀ ele.฀Repare฀que฀vou฀fazer฀uma฀pequena฀ Ve ã
código.฀O฀segundo฀processo฀traz฀a฀van- mudança฀no฀script,฀passando฀o฀arquivo฀ hile ead N
tagem฀de฀que,฀como฀o฀nome฀do฀arquivo฀ por฀redirecionamento฀de฀entrada฀(<),฀e฀ d
está฀antes฀do฀while,฀a฀visualização฀do฀ as฀coisas฀passarão฀a฀funcionar฀na฀mais฀ le C Li C a d
código฀é฀mais฀fácil.฀Entretanto,฀o฀Pipe฀ perfeita฀ordem: - a a ã al a li ha
(|)฀chama฀um฀subshell฀para฀interpretá-lo,฀ ech - $N
tornando฀o฀processo฀mais฀lento฀e฀pesado.฀ $ ca edi ead h C Li > de ll || ead
Para฀ilustrar฀o฀que฀foi฀dito,฀veja฀os฀exem- ! bi ba h d e < e
plos฀a฀seguir: edi ead h
E e l de ead a a d a i Na฀tentativa฀de฀fazer฀um฀programa฀
$ ca ead i e h i e genérico฀criamos฀a฀variável฀$C Li ฀(na฀
! bi ba h Ul i = a i vida฀real,฀os฀registros฀não฀são฀somente฀
ead i e h Pa a c i $ a a hile números฀seqüenciais)฀e,฀quando฀testamos฀
E e l de ead a a d a i hile ead Li ha se฀o฀resto฀da฀divisão฀era฀zero,฀mandamos฀
i e d a฀saída฀para฀ de ll,฀pra฀que฀ela฀não฀
Ul i = a i Ul i = $Li ha apareça฀na฀tela.฀Mas฀quando฀fui฀executar฀
Pa a c i $ a a hile ech -$Ul i - o฀programa฀descobri฀a฀seguinte฀zebra:
ca $ | hile ead Li ha d e < $
d ech Acab , Úl i =:$Ul i : $ ag h
Ul i = $Li ha 4 5 8 4 5 U
ech -$Ul i - Veja฀como฀ele฀roda฀perfeitamente: 8 4 5 8
d e
ech Acab , Úl i =:$Ul i : $ edi ead h Repare฀que฀faltou฀o฀número฀11฀e฀a฀lista-
- ! bi ba h- gem฀não฀parou฀no฀ ead.฀Toda฀a฀entrada฀do฀
Vamos฀ver฀o฀resultado฀de฀sua฀execução: - edi ead h- loop฀estava฀redirecionada฀para฀o฀arquivo฀
- E e l de ead a a d a i e ฀e฀a฀leitura฀foi฀feita฀em฀cima฀desse฀
$ ead i e h - i e - arquivo,฀perdendo฀o฀número฀11.฀Vamos฀
- ! bi ba h- -- mostrar฀como฀deveria฀ficar฀o฀código฀para฀
- ead i e h- -Ul i = a i - que฀ele฀passe฀a฀funcionar฀a฀contento:
- E e l de ead a a d a i - hile ead Li ha-
- i e - -d - $ ca ag h
-- -Ul i = $Li ha - ! bi ba h
-Ul i = a i - -ech -$Ul i - - P g a a de e e a a e c e e
- Pa a c i $ a a hile- - Pa a c i $ a a hile- li ha e a a a a le - Ve ã
-ca $ | - -d e < $ - hile ead N
- hile ead Li ha- -ech Acab , Úl i =:$Ul i : - d
-d - Acab , Úl i =:ech Acab ,U le C Li C a d
-Ul i = $Li ha - Úl i =:$Ul i : : - a a ã al a li ha
-ech -$Ul i - - ech - $N
-d e- Bem,฀amigos฀da฀Rede฀Shell,฀para฀finali- C Li > de ll || ead U
-ech Acab , Úl i =:$Ul i : - zar฀a฀aula฀sobre฀o฀comando฀ ead฀só฀falta฀ < de
Acab , Úl i =: a i : mais฀um฀pequeno฀e฀importante฀macete฀ d e < e

90 abril฀2005฀ edição฀07
[Link]
Papo฀de฀botequim฀ Linux฀User

Repare฀que฀agora฀a฀entrada฀do฀ ead฀foi฀ li ha e a a a a le –฀฀Bem฀meu฀amigo,฀por฀hoje฀é฀só฀porque฀


redirecionada฀para฀ de ,฀que฀nada฀ Ve ã acho฀que฀você฀já฀está฀de฀saco฀cheio…
mais฀é฀senão฀o฀terminal฀corrente,฀expli- clea –฀Num฀tô฀não,฀pode฀continuar…
citando฀desta฀forma฀que฀aquela฀leitura฀ hile ead N –฀฀Se฀você฀não฀estiver฀eu฀estou…฀Mas฀já฀
seria฀feita฀do฀teclado฀e฀não฀do฀arquivo฀ d que฀você฀está฀tão฀empolgado฀com฀o฀shell,฀
e .฀É฀bom฀realçar฀que฀isso฀não฀ C a d vou฀te฀deixar฀um฀serviço฀bastante฀sim-
acontece฀somente฀quando฀usamos฀o฀redi- C Li ples฀para฀você฀melhorar฀a฀sua฀cdteca:฀
recionamento฀de฀entrada;฀se฀tivéssemos฀ ech $N Monte฀toda฀a฀tela฀com฀um฀único฀ ech ฀
usado฀o฀redirecionamento฀via฀pipe฀(|),฀o฀ C Li ` li e ` - || e฀depois฀posicione฀o฀cursor฀à฀frente฀de฀
mesmo฀teria฀ocorrido.฀Veja฀agora฀a฀exe- { cada฀campo฀para฀receber฀o฀valor฀que฀
cução฀do฀script: a a le al e ca ac e e será฀digitado฀pelo฀operador.฀
ead - - Tecle Alg < de Não฀se฀esqueçam฀que,฀em฀caso฀de฀
$ ag h li a a ela a a lei a qualquer฀dúvida฀ou฀falta฀de฀companhia฀
4 5 8 clea para฀um฀chope฀é฀só฀mandar฀um฀e-mail฀
4 5 8 } para฀[Link]@[Link].฀Vou฀aproveitar฀
4 5 8 d e < e também฀para฀fazer฀uma฀propaganda:฀
digam฀aos฀amigos฀que฀quem฀estiver฀a฀
Isso฀está฀quase฀bom,฀mas฀ainda฀falta฀ A฀mudança฀substancial฀feita฀neste฀exem- fim฀de฀fazer฀um฀curso฀“porreta”฀de฀pro-
um฀pouco฀para฀ficar฀excelente.฀Vamos฀ plo฀é฀com฀relação฀à฀quebra฀de฀página,฀já฀ gramação฀em฀shell฀deve฀mandar฀um฀e-
melhorar฀o฀exemplo฀para฀que฀você฀o฀ que฀ela฀é฀feita฀a฀cada฀quantidade-de-linhas- mail฀para฀[Link]@[Link]฀para฀
reproduza฀e฀teste฀(mas,฀antes฀de฀testar,฀ da-tela฀( li e )฀menos฀(-)฀três,฀isto฀ informar-se.฀Até฀mais!
aumente฀o฀número฀de฀registros฀em฀ e- é,฀se฀a฀tela฀tem฀25฀linhas,฀o฀programa฀
฀ou฀reduza฀o฀tamanho฀da฀tela,฀para฀ listará฀22฀registros฀e฀parará฀para฀leitura.฀ Informações
que฀haja฀quebra฀de฀linha). No฀comando฀ ead฀também฀foi฀feita฀uma฀ [1] Página oficial do Tput: [Link]
alteração,฀inserido฀o฀parâmetro฀- ฀para฀ dept/old/texinfo/tput/[Link]#SEC4
$ ca ag h ler฀somente฀um฀caractere฀qualquer,฀não฀
[2] Página oficial do Bash: [Link]
! bi ba h necessariamente฀um฀ENTER,฀e฀a฀opção฀ software/bash/[Link]
P g a a de e e a a e c e e - ฀para฀exibir฀uma฀mensagem.

abril฀2005฀ edição฀07 91
[Link]
Linux฀User Papo฀de฀botequim

Papo฀de฀Botequim
Curso de Shell Script

Parte฀VIII

Dave Hamilton - [Link]


Chegou a hora de fazer como Jack e dividir os programas
em pedacinhos. Com funções e chamadas externas
os scripts ficam menores, a manutenção mais fácil
e ainda por cima reaproveitamos código.
por฀Júlio฀Cezar฀Neves

E
aê,฀cara,฀tudo฀bem? posicionais฀($ , $ , …, $ ).฀Todas฀as฀regras฀que฀se฀aplicam฀
– –฀฀Tudo฀beleza!฀Eu฀queria฀te฀mostrar฀o฀que฀fi฀z฀mas฀já฀sei฀ à฀passagem฀de฀parâmetros฀para฀programas฀também฀valem฀para฀
que฀você฀vai฀querer฀molhar฀o฀bico฀primeiro,฀né? funções,฀mas฀é฀muito฀importante฀realçar฀que฀os฀parâmetros฀
–฀฀ Só฀pra฀te฀contrariar,฀hoje฀não฀quero.฀Vai,฀mostra฀logo฀aí฀ passados฀para฀um฀programa฀não฀se฀confundem฀com฀aqueles฀
o฀que฀você฀fez. que฀são฀passados฀para฀suas฀funções.฀Isso฀signifi฀ca,฀por฀exem-
–฀฀Poxa,฀o฀exercício฀que฀você฀passou฀é฀muito฀grande.฀Dá฀uma฀ plo,฀que฀o฀ $ ฀de฀um฀script฀é฀diferente฀do฀ $ ฀de฀uma฀de฀suas฀
olhada฀na฀listagem 1฀e฀vê฀como฀eu฀resolvi: funções฀internas.
–฀฀ É,฀o฀programa฀tá฀legal,฀tá฀todo฀estruturadinho,฀mas฀gosta- Repare฀que฀as฀variáveis฀ $M g, $Ta M g฀e฀ $C l฀são฀de฀uso฀
ria฀de฀fazer฀alguns฀poucos฀comentários:฀só฀para฀relembrar,฀ restrito฀dessa฀rotina฀e,฀por฀isso,฀foram฀criadas฀como฀variáveis฀
as฀seguintes฀construções:฀[ ! $Alb ] &&฀e฀[ $M ica ] locais.฀A฀razão฀é฀simplesmente฀a฀economia฀de฀memória,฀já฀que฀
||฀representam฀a฀mesma฀coisa,฀isto฀é:฀no฀caso฀da฀primeira,฀ ao฀sair฀da฀rotina฀elas฀serão฀devidamente฀detonadas,฀coisa฀que฀
testamos฀se฀a฀variável฀$Alb ฀não฀(!)฀tem฀nada฀dentro,฀então฀ não฀aconteceria฀se฀eu฀não฀tivesse฀usado฀esse฀artifício.
(&&)…฀Na฀segunda,฀testamos฀se฀ $M ica฀tem฀algum฀dado,฀ A฀linha฀de฀código฀que฀cria฀a฀variável฀local฀M g฀concatena฀ao฀
senão฀(||)… texto฀recebido฀($ )฀um฀parêntese,฀a฀resposta฀padrão฀($ )฀em฀
Se฀você฀reclamou฀do฀tamanho฀do฀programa,฀é฀porque฀ainda฀ caixa฀alta,฀uma฀barra,฀a฀outra฀resposta฀($ )฀em฀caixa฀baixa฀
não฀te฀dei฀algumas฀dicas.฀Repare฀que฀a฀maior฀parte฀do฀script฀ e฀fi฀naliza฀fechando฀o฀parêntese.฀Uso฀essa฀convenção฀para,฀ao฀
é฀para฀mostrar฀mensagens฀centraliza-
das฀na฀penúltima฀linha฀da฀tela.฀Repare฀ Listagem 1: [Link]
ainda฀que฀algumas฀mensagens฀pedem฀
$ ca i c5 h
um฀S฀ou฀um฀N฀como฀resposta฀e฀outras฀
! bi ba h
são฀só฀de฀advertência.฀Isso฀é฀um฀caso฀
Cada a CD e a 5
típico฀que฀pede฀o฀uso฀de฀funções,฀que฀
4
seriam฀escritas฀somente฀uma฀vez฀e฀
5 clea
executadas฀em฀diversos฀pontos฀do฀
Li haMe g=$ ` li e ` - Li ha de e ã ada a g a a e ad
script.฀Vou฀montar฀duas฀funções฀para฀
T C l =$ c l Q d c l a da ela a a e ad a g
resolver฀esses฀casos฀e฀vamos฀incor-
8 ech
porá-las฀ao฀seu฀programa฀para฀ver฀o฀
I cl ã de M ica
resultado฀fi฀nal.
======== == =======
–฀฀Chico!฀Agora฀traz฀dois฀chopes,฀um฀
Tí l d Álb :
sem฀colarinho,฀para฀me฀dar฀inspira-
| E e ca f i
ção.฀E฀você,฀de฀olho฀na฀listagem 2.
Fai a: < c iad e e a a
Como฀podemos฀ver,฀uma฀função฀é฀
| ie a ee chi e
defi฀nida฀quando฀digitamos฀ e da
N e da M ica:
f çã ฀e฀todo฀o฀seu฀corpo฀está฀
I é e e: Tela ada c ic ech
entre฀chaves฀({}).฀Já฀conversamos฀aqui฀
hile e
no฀boteco฀sobre฀passagem฀de฀parâ-
d
metros฀e฀as฀funções฀os฀recebem฀da฀
c 5 8 el P ici a e li a li ha ➟
mesma฀forma,฀isto฀é,฀são฀parâmetros฀

86 maio฀2005฀ edição฀08
[Link]
papo฀de฀botequim Linux฀User

ead Alb mesmo฀tempo,฀mostrar฀as฀opções฀dis-


[ ! $Alb ] && O e ad de <ENTER> poníveis฀e฀realçar฀a฀resposta฀oferecida฀
4 { como฀padrão.
5 M g= De eja Te i a S Quase฀no฀fim฀da฀rotina,฀a฀resposta฀
Ta M g=${ M g} recebida฀($SN)฀é฀convertida฀para฀caixa฀
C l=$ T C l - Ta M g Ce ali a g a li ha baixa฀(minúsculas)฀de฀forma฀que฀no฀
8 c $Li haMe g $C l corpo฀do฀programa฀não฀precisemos฀
ech $M g fazer฀ esse฀ teste.฀ Veja฀ na฀ listagem 3฀
c $Li haMe g $ C l Ta M g como฀ficaria฀a฀função฀para฀exibir฀uma฀
ead - SN mensagem฀na฀tela.
c $Li haMe g $C l el A aga g da ela Essa฀é฀uma฀outra฀forma฀de฀definir฀
[ $SN = N - $SN = ] && c i e $SN é ig al a N - uma฀função:฀não฀a฀chamamos,฀como฀
4 clea e i Fi da e ec çã no฀ exemplo฀ anterior,฀ usando฀ uma฀
5 } construção฀com฀a฀sintaxe฀ e da
g e ^$Alb \^ ica > de ll && f çã ,฀mas฀sim฀como฀f c i
{ e da f çã .฀Em฀nada฀mais฀ela฀
8 M g= E e álb já e á cada ad difere฀da฀anterior,฀exceto฀que,฀como฀
Ta M g=${ M g} consta฀dos฀comentários,฀usamos฀a฀
C l=$ T C l - Ta M g Ce ali a g a li ha variável฀ $*฀que,฀como฀já฀sabemos,฀
c $Li haMe g $C l representa฀o฀conjunto฀de฀todos฀os฀
ech $M g parâmetros฀passados฀ao฀script,฀para฀
ead - que฀o฀programador฀não฀precise฀usar฀
4 c $Li haMe g $C l el A aga g da ela aspas฀envolvendo฀a฀mensagem฀que฀
5 c i e V l a a a le álb deseja฀passar฀à฀função.
} Para฀terminar฀com฀esse฀blá-blá-blá,฀
Reg= $Alb ^ $Reg ecebe á dad a a g a açã vamos฀ver฀na฀listagem 4฀as฀alterações฀
8 A i a= Va iá el e g a da a i a a e i no฀programa฀quando฀usamos฀o฀con-
hile e ceito฀de฀funções:
4 d Repare฀que฀a฀estrutura฀do฀script฀
4 Fai a segue฀a฀ordem฀Variáveis฀Globais,฀Fun-
4 c 8 ções฀e฀Corpo฀do฀Programa.฀Esta฀estrutu-
4 ech $Fai a ração฀se฀deve฀ao฀fato฀de฀Shell฀Script฀ser฀
44 c 8 P ici a a a le ica uma฀linguagem฀interpretada,฀em฀que฀
45 ead M ica
o฀programa฀é฀lido฀da฀esquerda฀para฀
4 [ $M ica ] || Se e ad i e dad <ENTER>
a฀direita฀e฀de฀cima฀para฀baixo.฀Para฀
4 {
ser฀vista฀pelo฀script฀e฀suas฀funções,฀
48 M g= Fi de Álb S
uma฀variável฀deve฀ser฀declarada฀(ou฀
4 Ta M g=${ M g}
inicializada,฀como฀preferem฀alguns)฀
5 C l=$ T C l - Ta M g Ce ali a g a li ha
antes฀de฀qualquer฀outra฀coisa.฀Por฀sua฀
5 c $Li haMe g $C l
vez,฀as฀funções฀devem฀ser฀declaradas฀
5 ech $M g
antes฀do฀corpo฀do฀programa฀propria-
5 c $Li haMe g $ C l Ta M g
mente฀dito.฀A฀explicação฀é฀simples:฀o฀
54 ead - SN
interpretador฀de฀comandos฀do฀shell฀
55 c $Li haMe g $C l el A aga g da ela
deve฀saber฀do฀que฀se฀trata฀a฀função฀
5 [ $SN = N - $SN = ] && c i e $SN é ig al a N -
antes฀que฀ela฀seja฀chamada฀no฀pro-
5 b eak Sai d l a a g a a
grama฀principal.
58 }
Uma฀coisa฀bacana฀na฀criação฀de฀fun-
5 c 8 P ici a a a le A i a
ções฀é฀fazê-las฀tão฀genéricas฀quanto฀
[ $ A i a ] && ech - $ A i a A i a a e i é defa l
possível,฀de฀forma฀que฀possam฀ser฀
ead A i a
reutilizadas฀em฀outros฀scripts฀e฀apli-
[ $A i a ] && A i a= $A i a
cativos฀sem฀a฀necessidade฀de฀reinven-
Reg= $Reg$ A i a~$M ica: M a d egi
tarmos฀a฀roda.฀As฀duas฀funções฀que฀
4 c 8 el A aga M ica da ela
acabamos฀de฀ver฀são฀bons฀exemplos,฀
5 c 8 el A aga A i a da ela
pois฀é฀difícil฀um฀script฀de฀entrada฀de฀
d e
dados฀que฀não฀use฀uma฀rotina฀como฀
ech $Reg >> ica G a a egi fi d a i
a฀Ma daM g฀ou฀que฀não฀interaja฀com฀
8 ica - ica Cla ifica a i
o฀operador฀por฀meio฀de฀algo฀seme-
d e
lhante฀à฀Pe g a.

maio฀2005฀ edição฀08 87
[Link]
Linux฀User Papo฀de฀botequim

Conselho฀de฀amigo:฀crie฀um฀arquivo฀e฀anexe฀a฀ele฀cada฀fun- diretório฀ h e.฀Só฀que฀assim฀que฀a฀execução฀do฀script฀termi-


ção฀nova฀que฀você฀criar.฀Ao฀final฀de฀algum฀tempo฀você฀terá฀ nou,฀o฀sub-shell฀foi฀para฀o฀beleléu฀e,฀com฀ele,฀todo฀o฀ambiente฀
uma฀bela฀biblioteca฀de฀funções฀que฀lhe฀poupará฀muito฀tempo฀ criado.฀Agora฀preste฀atenção฀no฀exemplo฀abaixo฀e฀veja฀como฀a฀
de฀programação. coisa฀muda฀de฀figura:

O comando source $ ce c i b b
Veja฀se฀você฀nota฀algo฀de฀diferente฀na฀saída฀do฀ls฀a฀seguir: j e e j lia a a la il ie
$ d
$ l -la ba h file h e
- - -- -- J li k 45 Ma 8 :45 ba h file $ cd -
h e j e e
Não฀olhe฀a฀resposta฀não,฀volte฀a฀prestar฀atenção!฀Bem,฀já฀que฀ $ c i b b
você฀está฀mesmo฀sem฀saco฀de฀pensar฀e฀prefere฀ler฀a฀resposta,฀ j e e j lia a a la il ie
vou฀te฀dar฀uma฀dica:฀acho฀que฀você฀já฀sabe฀que฀o฀ ba h - $ d
file฀é฀um฀dos฀scripts฀que฀são฀automaticamente฀executados฀ h e
quando฀você฀se฀“loga”฀(ARRGGHH!฀Odeio฀
esse฀termo!)฀no฀sistema.฀Agora฀olhe฀nova- Listagem 2: Função Pergunta
mente฀para฀a฀saída฀do฀comando฀ls฀e฀me฀
Pe g a
diga฀o฀que฀há฀de฀diferente฀nela.
{
Como฀eu฀disse,฀o฀ ba h file฀é฀exe-
A f çã ecebe a â e a eg i e de :
cutado฀durante฀o฀logon,฀mas฀repare฀que฀ele฀
não฀tem฀nenhuma฀permissão฀de฀execução.฀ 4 $ - Me age a e ada a ela
Isso฀acontece฀porque฀se฀você฀o฀executasse฀ 5 $ - Val a e acei c e a ad ã
como฀qualquer฀outro฀script฀careta,฀no฀fim฀ $ - O al acei
de฀sua฀execução฀todo฀o฀ambiente฀por฀ele฀ S d e $ =Acei a , $ = e $ = , a li ha a
gerado฀morreria฀junto฀com฀o฀shell฀sob฀o฀ 8 eg i c l ca ia e M g al Acei a S
qual฀ele฀foi฀executado฀(você฀se฀lembra฀de฀ l cal M g= $ `ech $ | a- A-Z` `ech $ | A-Z a- `
que฀todos฀os฀scripts฀são฀executados฀em฀ l cal Ta M g=${ M g}
sub-shells,฀né?).฀Pois฀é฀para฀coisas฀assim฀ l cal C l=$ T C l - Ta M g Ce a g a li ha
que฀existe฀o฀comando฀source,฀também฀ c $Li haMe g $C l
conhecido฀por฀“.”฀(ponto).฀Este฀comando฀ ech $M g
faz฀com฀que฀o฀script฀que฀lhe฀for฀passado฀ 4 c $Li haMe g $ C l Ta M g
como฀parâmetro฀não฀seja฀executado฀em฀ 5 ead - SN
um฀sub-shell.฀Mas฀é฀melhor฀um฀exemplo฀ [ ! $SN ] && SN=$ Se a ia c l ca defa l e SN
que฀uma฀explicação฀em฀453฀palavras.฀Veja฀ ech $SN | A-Z a- A aída de SN e á e i c la
o฀scriptzinho฀a฀seguir: 8 c $Li haMe g $C l el A aga g da ela
e Sai da f çã
$ ca c i b b }
cd
l
Listagem 3: Função MandaMsg
Ele฀simplesmente฀deveria฀ir฀para฀o฀dire-
f c i Ma daM g
tório฀ acima฀ do฀ diretório฀ atual.฀ Vamos฀
{
executar฀ uns฀ comandos฀ envolvendo฀ o฀
A f çã ecebe e e a â e
c i b b ฀e฀analisar฀os฀resultados:
4 c a e age e e de eja e ibi
5 a a ã b iga g a ad a a a
$ d
a g e e a a , a e $* d
h e j e e
a â e , le b a e ã $
$ c i b b
8 l cal M g= $*
j e e j lia a a la il ie
l cal Ta M g=${ M g}
$ d
l cal C l=$ T C l - Ta M g Ce a g a li ha
h e j e e
c $Li haMe g $C l
ech $M g
Se฀eu฀mandei฀ele฀subir฀um฀diretório,฀
ead -
por฀que฀não฀subiu?฀Opa,฀peraí฀que฀subiu฀
4 c $Li haMe g $C l el A aga g da ela
sim!฀O฀sub-shell฀que฀foi฀criado฀para฀exe-
5 e Sai da f çã
cutar฀o฀script฀tanto฀subiu฀que฀listou฀os฀
}
diretórios฀dos฀quatro฀usuários฀abaixo฀do฀

88 maio฀2005฀ edição฀08
[Link]
papo฀de฀botequim Linux฀User

Listagem 4: [Link] 5 ech


I cl ã de M ica
$ ca i c
======== == =======
! bi ba h
Tí l d Álb :
Cada a CD e a
Fai a:
4
N e da M ica:
5 Á ea de a iá ei gl bai
I é e e:
Li ha de a e age e ã e ibida
5 hile e
Li haMe g=$ ` li e ` -
54 d
8 Q a idade de c l a a ela a a e ad a a e age
55 c 5 8 el P ici a e li a li ha
T C l =$ c l
5 ead Alb
Á ea de f ç e
5 [ ! $Alb ] && O e ad de <ENTER>
Pe g a
58 {
{
5 Pe g a De eja Te i a
A f çã ecebe a â e a eg i e de :
Ag a e cai a bai a
4 $ - Me age a e dada a ela
[ $SN = ] && c i e
5 $ - Val a e acei c e a defa l
clea e i Fi da e ec çã
$ - O al acei
}
S d e $ =Acei a , $ = e $ = , a li ha
4 g e -i ^$Alb \^ ica > de ll &&
8 abai c l ca ia e M g al Acei a S
5 {
l cal M g= $ `ech $ | a- A-Z` `ech $ | A-Z a- `
Ma daM g E e álb já e á cada ad
l cal Ta M g=${ M g}
c i e V l a a a le álb
Ce ali a a e age a li ha
8 }
l cal C l=$ T C l - Ta M g
Reg= $Alb ^ $Reg ecebe á dad de g a açã
c $Li haMe g $C l
A i a= G a da á a i a a e i
4 ech $M g
hile e
5 c $Li haMe g $ C l Ta M g
d
ead - SN
Fai a
[ ! $SN ] && SN=$ Se a ia, c l ca defa l e SN
4 c 8
8 ech $SN | A-Z a- A aída de SN e á e i c la
5 ech $Fai a
c $Li haMe g $C l el A aga g da ela
c 8 P ici a a a le ica
e Sai da f çã
ead M ica
}
8 [ $M ica ] || Se e ad ecl <ENTER>
f c i Ma daM g
{
{
8 Pe g a Fi de Álb
4 A f çã ecebe e e a â e
8 Ag a e a cai a bai a
5 c a e age e e de eja e ibi
8 [ $SN = ] && c i e
a a ã b iga g a ad a a a
8 b eak Sai d l a a g a a dad
a g e e a a , a e $* d
84 }
8 a â e , le b a e ã $
85 c 8 P ici a a a le A i a
l cal M g= $*
8 O a i a a e i é ad ã
4 l cal Ta M g=${ M g}
8 [ $ A i a ] && ech - $ A i a
4 Ce ali a e age a li ha
88 ead A i a
4 l cal C l=$ T C l - Ta M g
8 [ $A i a ] && A i a= $A i a
4 c $Li haMe g $C l
Reg= $Reg$ A i a~$M ica: M a d egi
44 ech $M g
c 8 el A aga M ica da ela
45 ead -
c 8 el A aga A i a da ela
4 c $Li haMe g $C l el A aga g da ela
d e
4 e Sai da f çã
4 G a a egi fi d a i
48 }
5 ech $Reg >> ica
4 O c d g a a ia e e di c eça a i
Cla ifica a i
5 clea
ica - ica
5 A ela a eg i é ada c ic c a d ech
8 d e

maio฀2005฀ edição฀08 89
[Link]
Linux฀User Papo฀de฀botequim

Listagem 5: [Link] Ahh!฀Agora฀sim!฀Quando฀passado฀


como฀parâmetro฀do฀comando฀source,฀
$ ca i c h
o฀ script฀ foi฀ executado฀ no฀ shell฀ cor-
! bi ba h
Cada a CD e a
rente,฀deixando฀nele฀todo฀o฀ambiente฀
4 criado.฀Agora฀vamos฀rebobinar฀a฀fita฀
5 Á ea de a iá ei gl bai até฀o฀início฀da฀explicação฀sobre฀este฀
Li haMe g=$ ` li e ` - Li ha de e ã ada a g a a e ad comando.฀Lá฀falamos฀do฀ ba h -
T C l =$ c l Q d c l a da ela a a e ad a g file฀e,฀a฀esta฀altura,฀você฀já฀deve฀saber฀
8 O c d g a a ia e e di c eça a i que฀sua฀incumbência฀é,฀logo฀após฀o฀
clea login,฀preparar฀o฀ambiente฀de฀trabalho฀
ech para฀o฀usuário.฀Agora฀entendemos฀que฀
I cl ã de M ica é฀por฀isso฀mesmo฀que฀ele฀é฀executado฀
======== == ======= usando฀esse฀artifício.
Tí l d Álb : E฀ agora฀ você฀ deve฀ estar฀ se฀ per-
| E e ca f i guntando฀se฀é฀só฀para฀isso฀que฀esse฀
Fai a: < c iad e e a a comando฀serve.฀Eu฀lhe฀digo฀que฀sim,฀
| ie a ee chi e mas฀isso฀nos฀traz฀um฀monte฀de฀vanta-
N e da M ica:
gens฀–฀e฀uma฀das฀mais฀usadas฀é฀tratar฀
I é e e: Tela ada c ic ech
funções฀como฀rotinas฀externas.฀Veja฀
hile e
na฀listagem 5฀uma฀outra฀forma฀de฀fazer฀
d
o฀nosso฀programa฀para฀incluir฀CDs฀no฀
c 5 8 el P ici a e li a li ha
4 ead Alb
arquivo฀musicas.
5 [ ! $Alb ] && O e ad de <ENTER> Agora฀o฀programa฀deu฀uma฀boa฀enco-
{ lhida฀e฀as฀chamadas฀de฀função฀foram฀
ce e g a f c De eja Te i a trocadas฀por฀arquivos฀externos฀chama-
8 [ $SN = ] && c i e Ag a e a cai a bai a dos฀ e g a f c฀e฀ a da g f c,฀
clea e i Fi da e ec çã que฀assim฀podem฀ser฀chamados฀por฀
} qualquer฀outro฀programa,฀dessa฀forma฀
g e -i ^$Alb \^ ica > de ll && reutilizando฀o฀seu฀código.
{ Por฀motivos฀meramente฀didáticos,฀as฀
a da g f c E e álb já e á cada ad chamadas฀a฀ e g a f c฀e฀ a da-
4 c i e V l a a a le álb g f c฀estão฀sendo฀feitas฀por฀source฀
5 } e฀por฀ ฀(ponto)฀indiscriminadamente,฀
Reg= $Alb ^ $Reg ecebe á dad de g a açã embora฀eu฀prefira฀o฀source฀que,฀por฀
A i a= G a da á a i a a e i
ser฀mais฀visível,฀melhora฀a฀legibili-
8 hile e
dade฀do฀código฀e฀facilita฀sua฀posterior฀
d
manutenção.฀Veja฀na฀listagem฀6฀como฀
Fai a
ficaram฀esses฀dois฀arquivos.
c 8
Em฀ambos฀os฀arquivos,฀fiz฀somente฀
ech $Fai a
c 8 P ici a a a le ica duas฀ mudanças,฀ que฀ veremos฀ nas฀
4 ead M ica observações฀a฀seguir.฀Porém,฀tenho฀
5 [ $M ica ] || Se e ad i e dad <ENTER> mais฀três฀observações฀a฀fazer:
{ 1. As฀variáveis฀não฀estão฀sendo฀mais฀
e g a f c Fi de Álb declaradas฀como฀locais,฀porque฀essa฀
8 [ $SN = ] && c i e Ag a e a cai a bai a é฀uma฀diretiva฀que฀só฀pode฀ser฀usada฀
b eak Sai d l a a g a a dad no฀corpo฀de฀funções฀e,฀portanto,฀essas฀
4 } variáveis฀permanecem฀no฀ambiente฀do฀
4 c 8 P ici a a a le A i a shell,฀poluindo-o;
4 [ $ A i a ] && ech - $ A i a A i a a e i é defa l 2. O฀comando฀return฀não฀está฀mais฀
4 ead A i a presente,฀mas฀poderia฀estar฀sem฀alte-
44 [ $A i a ] && A i a= $A i a rar฀em฀nada฀a฀lógica฀do฀script,฀uma฀
45 Reg= $Reg$ A i a~$M ica: M a d egi vez฀que฀só฀serviria฀para฀indicar฀um฀
4 c 8 el A aga M ica da ela
eventual฀erro฀por฀meio฀de฀um฀código฀
4 c 8 el A aga A i a da ela
de฀retorno฀previamente฀estabelecido฀
48 d e
(por฀exemplo฀ e ,฀ e ,฀…),฀
4 ech $Reg >> ica G a a egi fi d a i
sendo฀que฀o฀ e ฀e฀ e ฀são฀
5 ica - ica Cla ifica a i
5 d e
idênticos฀e฀significam฀que฀a฀rotina฀foi฀
executada฀sem฀erros;

90 maio฀2005฀ edição฀08
[Link]
papo฀de฀botequim Linux฀User

3. O฀comando฀que฀estamos฀acostumados฀ Listagem 6: [Link] e [Link]


a฀usar฀para฀gerar฀um฀código฀de฀retorno฀
$ ca e g a f c
é฀o฀exit,฀mas฀a฀฀saída฀de฀uma฀rotina฀
A f çã ecebe a â e a eg i e de :
externa฀não฀pode฀ser฀feita฀dessa฀forma฀
$ - Me age a e dada a ela
porque,฀como฀ela฀está฀sendo฀executada฀
4 $ - Val a e acei c e a defa l
no฀mesmo฀shell฀do฀script฀que฀o฀cha-
5 $ - O al acei
mou,฀o฀exit฀simplesmente฀encerraria฀
S d e $ =Acei a , $ = e $ = , a li ha
esse฀shell,฀terminando฀a฀execução฀de฀
abai c l ca ia e M g al Acei a S
todo฀o฀script;
8 M g= $ `ech $ | a- A-Z` `ech $ | A-Z a- `
4. De฀onde฀veio฀a฀variável฀Li haMe g?฀Ela฀
Ta M g=${ M g}
veio฀do฀script฀ i c h,฀porque฀havia฀
C l=$ T C l - Ta M g Ce ali a g a li ha
sido฀declarada฀antes฀da฀chamada฀das฀
c $Li haMe g $C l
rotinas฀(nunca฀esqueça฀que฀o฀shell฀que฀
ech $M g
está฀interpretando฀o฀script฀e฀essas฀roti-
c $Li haMe g $ C l Ta M g
nas฀é฀o฀mesmo);
4 ead - SN
5. Se฀você฀decidir฀usar฀rotinas฀externas฀
5 [ ! $SN ] && SN=$ Se a ia c l ca defa l e SN
não฀se฀envergonhe,฀exagere฀nos฀comen-
ech $SN | A-Z a- A aída de SN e á e i c la
tários,฀principalmente฀sobre฀a฀passagem฀
c $Li haMe g $C l el A aga g da ela
dos฀parâmetros,฀para฀facilitar฀a฀manu-
8 $ ca a da g f c
tenção฀e฀o฀uso฀dessa฀rotina฀por฀outros฀
A f çã ecebe e e a â e
programas฀no฀futuro.
c a e age e e de eja e ibi
–฀฀Bem,฀ agora฀ você฀ já฀ tem฀ mais฀ um฀
a a ã b iga g a ad a a a
monte฀de฀novidades฀para฀ melhorar฀
a g e e a a , a e $* d
os฀scripts฀que฀fizemos.฀Você฀se฀lem-
a â e , le b a e ã $
bra฀do฀programa฀[Link]฀no฀qual฀
4 M g= $*
você฀passava฀o฀nome฀de฀um฀artista฀
5 Ta M g=${ M g}
como฀parâmetro฀e฀ele฀devolvia฀as฀suas฀
C l=$ T C l - Ta M g Ce ali a g a li ha
músicas?฀Ele฀era฀como฀o฀mostrado฀aqui฀
c $Li haMe g $C l
embaixo฀na฀listagem 7.
8 ech $M g
–฀Claro฀que฀me฀lembro!
ead -
–฀฀Para฀firmar฀os฀conceitos฀que฀te฀pas-
c $Li haMe g $C l el A aga g da ela
sei,฀faça-o฀com฀a฀tela฀formatada฀e฀a฀
execução฀em฀loop,฀de฀forma฀que฀ele฀
só฀termine฀quando฀receber฀um฀Enter฀no฀lugar฀do฀nome฀ Não฀ se฀ esqueça:฀ em฀ caso฀ de฀ dúvida฀ ou฀ falta฀ de฀ compa-
do฀artista.฀Suponha฀que฀a฀tela฀tenha฀25฀linhas;฀a฀cada฀22฀ nhia฀para฀um฀chope,฀é฀só฀mandar฀um฀e-mail฀para฀o฀endereço฀
músicas฀listadas฀o฀programa฀deverá฀dar฀uma฀parada฀para฀ [Link]@[Link]฀que฀terei฀prazer฀em฀lhe฀ajudar.฀Vou฀aproveitar฀
que฀o฀operador฀possa฀lê-las.฀Eventuais฀mensagens฀de฀erro฀ também฀para฀mandar฀minha฀propaganda:฀diga฀aos฀amigos฀que฀
devem฀ser฀passadas฀usando฀a฀rotina฀ a da g f c฀que฀ quem฀estiver฀a฀fim฀de฀fazer฀um฀curso฀porreta฀de฀programação฀
acabamos฀de฀desenvolver.฀Chico,฀manda฀mais฀dois!!฀O฀meu฀ em฀Shell฀deve฀mandar฀um฀e-mail฀para฀[Link]@[Link]฀
é฀com฀pouca฀pressão… para฀informar-se.฀Até฀mais!฀ ■

Listagem 7: [Link] Informações


$ ca li a i a h [1] Bash, página oficial:
! bi ba h [Link]
Dad a i a, a a a ica
[2] Manual de referência do Bash:
4 e a [Link]
5 if [ $ -e ] manual/[Link]
he
ech V ce de e ia e a ad el e a a e
8 e i
Julio Cezar Neves é Analista de Suporte de
Sobre฀o฀autor

fi
Sistemas desde 1969 e trabalha com Unix
IFS=
: desde 1980, quando participou do desen-
f A M i $ c -f -d^ ica volvimento do SOX, um sistema operacio-
d nal similar ao Unix produzido pela Cobra
4 ech $A M | g e -i ^$*~ > de ll && ech $A M | c -f -d~ Computadores. Pode ser contatado no
5 d e e-mail [Link]@[Link]

maio฀2005฀ edição฀08 91
[Link]
Linux฀User Papo฀de฀Botequim

Papo฀de฀Botequim
Curso de Shell Script

Parte฀IX

Dave Hamilton - [Link]


Hoje vamos aprender mais sobre formatação de cadeias de caracteres,
conhecer as principais variáveis do Shell e nos aventurar no (ainda)
desconhecido território da expansão de parâmetros. E dá-lhe chope!
por฀Júlio฀Cezar฀Neves

T
á฀bom,฀já฀sei฀que฀você฀vai฀querer฀chope฀antes฀de฀começar,฀ Bom,฀a฀resposta฀é฀"mais฀ou฀menos".฀Com฀estes฀comandos฀
mas฀tô฀tão฀a฀fi฀m฀de฀te฀mostrar฀o฀que฀fi฀z฀que฀já฀vou฀pedir฀a฀ você฀escreve฀90%฀do฀que฀precisa,฀porém฀se฀precisar฀escrever฀
rodada฀enquanto฀isso.฀Aê฀Chico,฀manda฀dois!฀O฀dele฀é฀sem฀ algo฀formatado฀eles฀lhe฀darão฀muito฀trabalho.฀Para฀formatar฀a฀
colarinho฀pra฀não฀deixar฀cheiro฀ruim฀nesse฀bigodão… saída฀veremos฀agora฀uma฀instrução฀muito฀mais฀interessante,฀
Enquanto฀o฀chope฀não฀chega,฀deixa฀eu฀te฀lembrar฀o฀que฀ a฀printf.฀Sua฀sintaxe฀é฀a฀seguinte:
você฀me฀pediu฀na฀edição฀passada:฀era฀para฀refazer฀
o฀programa฀listartista฀com฀a฀tela฀formatada฀e฀exe- Listagem 1: [Link] e [Link]
cução฀em฀loop,฀de฀forma฀que฀ele฀só฀termine฀quando฀ [Link]
receber฀um฀[ENTER]฀sozinho฀como฀nome฀do฀artista.฀ A f çã ecebe e e a â e
Eventuais฀mensagens฀de฀erro฀e฀perguntas฀feitas฀ao฀ c a e age e e de eja e ibi
usuário฀deveriam฀ser฀mostradas฀na฀antepenúltima฀ Pa a ã b iga g a ad a a a
linha฀da฀tela,฀utilizando฀para฀isso฀as฀rotinas฀externas฀ 4 a g e e a a , a e $* d
a da g f c฀e฀ e g a f c฀que฀desenvolvemos฀ 5 a â e , le b a e ã $
M g= $*
durante฀nosso฀papo฀na฀edição฀passada.฀
Ta M g=${ M g}
Primeiramente฀eu฀dei฀uma฀encolhida฀nas฀rotinas฀
8 C l=$ T C l - Ta M g Ce a g a li ha
a da g f c฀e฀ e g a f c,฀que฀fi฀caram฀como฀ c $Li haMe g $C l
na฀listagem 1.฀E฀na฀listagem 2฀você฀tem฀o฀“grandão”,฀ ead - - $M g
nossa฀versão฀refeita฀do฀listaartista.
–฀Puxa,฀você฀chegou฀com฀a฀corda฀toda!฀Gostei฀da฀ [Link]
forma฀como฀você฀resolveu฀o฀problema฀e฀estruturou฀ A f çã ecebe a â e a eg i e de :
$ - Me age a e ada a ela
o฀programa.฀Foi฀mais฀trabalhoso,฀mas฀a฀apresenta-
$ - Val a e acei c e a ad ã
ção฀fi฀cou฀muito฀legal฀e฀você฀explorou฀bastante฀as฀
4 $ - O al acei
opções฀do฀comando฀tput.฀Vamos฀testar฀o฀resultado฀
5 S d e $ =Acei a , $ = e $ = , a li ha
com฀um฀álbum฀do฀Emerson,฀Lake฀&฀Palmer฀que฀ abai c l ca ia e M g al Acei a S
tenho฀cadastrado. M g= $ `ech $ | a- A-Z` `ech $ | A-Z a- `
8 Ta M g=${ M g}
Envenenando a escrita C l=$ T C l - Ta M g Ce ali a g a li ha
Ufa!฀Agora฀você฀já฀sabe฀tudo฀sobre฀leitura฀de฀dados,฀ c $Li haMe g $C l
mas฀quanto฀à฀escrita฀ainda฀está฀apenas฀engatinhando.฀ ead - - $M g SN
[ ! $SN ] && SN=$ Se a ia c l ca defa l e SN
Já฀sei฀que฀você฀vai฀me฀perguntar:฀“Ora,฀não฀é฀com฀o฀
SN=$ ech $SN | A-Z a- A aída de SN e á e i c la
comando฀echo฀e฀com฀os฀redirecionamentos฀de฀saída฀
4 c $Li haMe g $C l el A aga g da ela
que฀se฀escreve฀dados?”.

84 junho฀2005฀ edição฀09
[Link]
Papo฀de฀Botequim Linux฀User

Listagem 2: listaartista
i f f a [a g e ] $ ca li a i a h
! bi ba h
Onde฀formato฀é฀uma฀cadeia฀ Dad a i a, a a a ica
e a
de฀caracteres฀que฀contém฀três฀
4 Li haMe g=$ ` li e ` - Li ha de a g e ã ada
tipos฀ de฀ objeto:฀ caracteres฀ 5 T C l =$ c l Q d de c l a a ela a a e ad a g
simples,฀caracteres฀para฀es- clea
pecificação฀de฀formato฀(ou฀de฀ ech
–––––––––––––––––-----------------------------------
controle)฀e฀seqüência฀de฀esca-
| Li a T da a M ica de De e i ad A i a |
pe฀no฀padrão฀da฀linguagem฀ | ===== ===== == ======= == == =========== ======= |
C.฀argumento฀é฀a฀cadeia฀de฀ | |
caracteres฀a฀ser฀impressa฀sob฀ | I f e A i a: |
––––––––––––––––----------------------------------–-
o฀controle฀de฀formato.
8 hile e
Cada฀um฀dos฀caracteres฀uti- d
lizados฀é฀precedido฀pelo฀ca- c 5 5 ech ech=E a e cha a a ã a aga ba a e ical
racter฀ ฀e,฀logo฀a฀seguir,฀vem฀ ead N e
a฀especificação฀de฀formato฀de฀ if [ ! $N e ] $N e e a a i
he
acordo฀com฀a฀tabela 1.
4 e g a f c De eja Sai
As฀ seqüências฀ de฀ escape฀ 5 [ $SN = ] && c i e
padrão฀da฀linguagem฀C฀são฀ b eak
sempre฀ precedidas฀ pelo฀ ca- fi
8 fg e -i ^$N e~ ica || fg e ã i e e a ^ c e e ã eg la
ractere฀contra-barra฀(\).฀As฀
{
reconhecidas฀pelo฀comando฀ a da g f c Nã e i e ica de e a i a
printf฀são฀as฀da฀tabela 2. c i e
Não฀acaba฀por฀aí฀não!฀Tem฀ }
c ech | |
muito฀mais฀coisa฀sobre฀essa฀
4 Li A al=8
instrução,฀mas฀como฀esse฀é฀ 5 IFS=
um฀assunto฀muito฀cheio฀de฀ :
detalhes฀ e,฀ portanto,฀ chato฀ f A M i $ c -f -d^ ica E cl i e d alb
8 d
para฀explicar฀e฀pior฀ainda฀para฀
if ech $A M | g e -i ^$N e~
ler฀ou฀estudar,฀vamos฀passar฀ he
direto฀aos฀exemplos฀com฀co- c $Li A al
mentários.฀Veja฀só: ech - |
ech $A M | c -f -d~
4 c $Li A al 8
$ i f c ca ac e
5 ech |
$ le Li A al
if [ $Li A al -e $Li haMe g ]
Errado!฀Só฀listou฀1฀caractere฀ 8 he
a da g f c Tecle Alg a a C i a
e฀não฀saltou฀linha฀ao฀final
4 c ed A aga a ela a a i da li ha
4 c ech | |
$ i f c\ ca ac e 4 Li A al=8
4 fi
44 fi
45 d e
Saltou฀linha฀mas฀ainda฀não฀ 4 c $Li A al ech | |
listou฀a฀cadeia฀inteira 4 c $ Li A al
48 ead - - –––--Tecle Alg a a N a C l a––––
4 c ed A aga a ela a a i da li ha
$ i f c ca ac e e\
5 d e
ca ac e e ➟

junho฀2005฀ edição฀09 85
[Link]
Linux฀User Papo฀de฀Botequim

Tabela 1: Formatos de caractere ( )฀significa฀o฀tamanho฀que฀a฀cadeia฀terá฀ O฀ bc฀devolveu฀duas฀casas฀decimais฀e฀


após฀a฀execução฀do฀comando.฀Vamos฀ver฀ o฀ i f฀colocou฀o฀zero฀à฀direita.฀O฀co-
Caractere A expressão será impressa como:
c Caractere simples a฀seguir฀mais฀alguns฀exemplos.฀Os฀co- mando฀a฀seguir:
d Número no sistema decimal mandos฀abaixo:
e Notação científica exponencial $ i f \
f Número com ponto decimal (float) $ i f d\
g O menor entre os formatos %e e %f com
omissão dos zeros não significativos $ i f d\ Converteu฀o฀valor฀ ฀para฀base฀octal.฀
o Número no sistema octal Para฀melhorar฀experimente:
s Cadeia de caracteres
x Número no sistema hexadecimal
preenchem฀a฀string฀com฀espaços฀em฀ $ i f \
% Imprime um %. Não há nenhum
tipo de conversão branco฀à฀esquerda฀(oito฀espaços฀mais฀dois฀
caracteres,฀10฀dígitos),฀não฀com฀zeros.฀Já฀
no฀comando฀abaixo: Assim฀a฀conversão฀fica฀com฀mais฀jeito฀
Opa,฀essa฀é฀a฀forma฀correta!฀O฀ c฀rece- de฀octal,฀né?.฀O฀que฀este฀aqui฀faz?
beu฀o฀valor฀ ,฀como฀queríamos: $ i f 4d\
$ i f \ Pe eleca
$ a= Pe eleca
$ i f c ca ac e e \ $a O฀ 4฀após฀ ฀significa฀“formate฀a฀string฀ $ i f 5 \ Pe eleca
ca ac e e em฀quatro฀dígitos,฀com฀zeros฀à฀esquerda฀ Pe eleca
se฀necessário”.฀No฀comando:
O฀ c฀recebeu฀o฀valor฀da฀variável฀$a. Imprime฀Pe eleca฀com฀15฀caracteres.฀
$ i f e\ $ ech cale= | bc A฀cadeia฀de฀caracteres฀é฀preenchida฀com฀
$ i f c ca ac e e \ $a e espaços฀em฀branco฀à฀esquerda.฀Já฀no฀co-
ca ac e e mando:
$ i f c\ $a ca ac e e O฀padrão฀do฀ e฀é฀seis฀casas฀decimais.฀
Já฀no฀comando: $ i f - 5 Ne e \ Pe eleca
c Pe eleca Ne e
$ i f e\ `ech cale= | bc`
Repare฀que,฀nos฀dois฀últimos฀exemplos,฀ e O฀menos฀(-)฀colocou฀espaços฀em฀branco฀
em฀virtude฀do฀uso฀do฀ c,฀só฀foi฀listado฀ à฀direita฀de฀Pe eleca฀até฀completar฀os฀15฀
um฀caractere฀de฀cada฀cadeia฀de฀caracteres฀ O฀ ฀especificou฀duas฀casas฀decimais.฀ caracteres฀pedidos.฀E฀o฀comando฀abaixo,฀
passada฀como฀parâmetro.฀O฀valor฀ ฀à฀ Observe฀agora: o฀que฀faz?
frente฀do฀c฀não฀significa฀10฀caracteres.฀Um฀
número฀seguindo฀o฀sinal฀de฀percentagem฀ $ i f f\ $ i f \ Pe eleca
Pe
Tabela 2: Seqüências de escape
O฀padrão฀do฀ f฀é฀seis฀casas฀decimais.฀ O฀ ฀manda฀truncar฀a฀cadeia฀de฀ca-
Seqüência Efeito
E฀no฀comando: racteres฀após฀as฀três฀primeiras฀letras.฀E฀
a Soa o beep
b Volta uma posição (backspace) o฀comando฀a฀seguir:
f Salta para a próxima página $ i f f\
lógica ( form feed) $ i f a\ Pe eleca
n Salta para o início da linha se- Pe a Pe
guinte (line feed) O฀ ฀especificou฀duas฀casas฀decimais.฀
r Volta para o início da linha cor-
Agora฀observe: Imprime฀a฀cadeia฀com฀10฀caracteres,฀
rente (carriage return)
truncada฀após฀os฀três฀primeiros,฀conca-
t Avança para a próxima marca de
tabulação $ i f f\ `ech cale= | bc` tenada฀com฀o฀caractere฀ a฀(após฀o฀ ).฀E฀
esse฀comando฀a฀seguir,฀o฀que฀faz?

86 junho฀2005฀ edição฀09
[Link]
Papo฀de฀Botequim Linux฀User

$ i f EXEMPLO \ 45 trabalho,฀principalmente฀em฀instalações฀ (1฀minuto).฀A฀cada฀intervalo฀o฀Shell฀fará฀


EXEMPLO b b com฀estrutura฀de฀diretórios฀em฀múltiplos฀ a฀verificação฀antes฀de฀exibir฀o฀próximo฀
níveis.฀Veja฀o฀exemplo฀a฀seguir: prompt฀primário฀($PS ).฀Se฀essa฀variável฀
Ele฀transformou฀o฀número฀45 ฀para฀ estiver฀sem฀valor฀ou฀com฀um฀valor฀menor฀
hexadecimal฀(b b ),฀mas฀os฀zeros฀não฀ $ ech $CDPATH ou฀igual฀a฀zero,฀a฀busca฀por฀novas฀men-
combinam฀com฀o฀resto.฀Experimente: : :~: l cal sagens฀não฀será฀efetuada.
$ d PATH฀»฀Caminhos฀que฀serão฀pesquisa-
$ i f EXEMPLO X\ 45 h e j e e LM dos฀para฀tentar฀localizar฀um฀arquivo฀espe-
EXEMPLO B B $ cd bi cificado.฀Como฀cada฀script฀é฀um฀arquivo,฀
$ d caso฀use฀o฀diretório฀corrente฀( )฀na฀sua฀
Assim฀disfarçou฀melhor!฀(repare฀no฀ X฀ l cal bi variável฀$PATH,฀você฀não฀necessitará฀usar฀
maiúsculo).฀Pra฀terminar,฀que฀tal฀o฀co- o฀comando฀ c ฀para฀que฀o฀script฀ c ฀
mando฀abaixo: Como฀ l cal฀estava฀na฀minha฀ seja฀executado.฀Basta฀digitar฀ c .฀Este฀
variável฀$CDPATH฀e฀não฀existia฀o฀diretório฀ é฀o฀modo฀que฀prefiro.
$ i f X XL X\ 4 54 bi ฀em฀nenhum฀dos฀seus฀antecessores฀( ,฀ PIPESTATUS฀»฀É฀uma฀variável฀do฀tipo฀
C CA C LA ฀e฀~),฀o฀comando฀cd฀foi฀executado฀tendo฀ vetor฀(array)฀que฀contém฀uma฀lista฀de฀
como฀destino฀ l cal bi . valores฀de฀códigos฀de฀retorno฀do฀último฀
Este฀aí฀não฀é฀marketing฀e฀é฀bastante฀ HISTSIZE฀»฀Limita฀o฀número฀de฀ins- pipeline฀executado,฀isto฀é,฀um฀array฀que฀
completo,฀veja฀só฀como฀funciona: truções฀que฀cabem฀dentro฀do฀arquivo฀de฀ abriga฀cada฀um฀dos฀$ ฀de฀cada฀instrução฀
O฀primeiro฀ X฀converteu฀4 54฀em฀he- histórico฀de฀comandos฀(normalmente฀ do฀último฀pipeline.฀Para฀entender฀melhor,฀
xadecimal,฀resultando฀em฀C0CA฀(leia-se฀ ba h hi ,฀mas฀na฀verdade฀é฀o฀que฀ veja฀o฀exemplo฀a฀seguir:
“cê”,฀“zero”,฀“cê”฀e฀“a”).฀Em฀seguida฀veio฀ está฀indicado฀na฀variável฀$HISTFILE).฀Seu฀
um฀espaço฀em฀branco฀seguido฀por฀outro฀ valor฀padrão฀é฀500. $ h
XL.฀O฀ X฀converteu฀o฀ ฀dando฀como฀ HOSTNAME฀»฀O฀nome฀do฀host฀corrente฀ j e e A : 4 44
resultado฀C ฀que฀com฀o฀L฀fez฀C L.฀E฀final- (que฀também฀pode฀ser฀obtido฀com฀o฀co- j e e A : 4 4 44
mente฀o฀último฀parâmetro฀ X฀transformou฀ mando฀ a e - ). $ h | g e ^b elh
o฀número฀ ฀na฀letra฀A. LANG฀»฀Usada฀para฀determinar฀o฀idioma฀ $ ech ${PIPESTATUS[*]}
Conforme฀vocês฀podem฀notar,฀a฀instru- falado฀no฀país฀(mais฀especificamente฀ca-
ção฀é฀bastante฀completa฀e฀complexa.฀Ain- tegoria฀do฀locale).฀Veja฀um฀exemplo:
da฀bem฀que฀o฀echo฀resolve฀quase฀tudo... Neste฀exemplo฀mostramos฀que฀o฀usu-
Acertei฀em฀cheio฀quando฀resolvi฀expli- $ da e ário฀ botelho฀ não฀ estava฀ “logado”,฀ em฀
car฀o฀ i f฀através฀de฀exemplos,฀pois฀ Th A 4 :54: BRT 5 seguida฀executamos฀um฀pipeline฀que฀
não฀saberia฀como฀enumerar฀tantas฀regri- $ LANG= BR da e procurava฀por฀ele.฀Usa-se฀a฀notação฀[*]฀
nhas฀sem฀tornar฀a฀leitura฀enfadonha. Q i Ab 4 :55: 4 BRT 5 em฀um฀array฀para฀listar฀todos฀os฀seus฀
elementos;฀dessa฀forma,฀vimos฀que฀a฀pri-
Principais variáveis do Shell LINENO฀»฀O฀número฀da฀linha฀do฀script฀ meira฀instrução฀( h )฀foi฀bem-sucedida฀
O฀Bash฀possui฀diversas฀variáveis฀que฀ ou฀ função฀ que฀ está฀ sendo฀ executada.฀ (código฀de฀retorno฀ )฀e฀a฀seguinte฀(g e )฀
servem฀ para฀ dar฀ informações฀ sobre฀ Seu฀uso฀principal฀é฀mostrar฀mensagens฀ não฀(código฀de฀retorno฀ ).
o฀ambiente฀ou฀alterá-lo.฀São฀muitas฀e฀ de฀erro฀juntamente฀com฀as฀variáveis฀ $ ฀ PROMPT COMMAND฀»฀Se฀esta฀variável฀re-
não฀pretendo฀mostrar฀todas฀elas,฀mas฀ (nome฀do฀programa)฀e฀$FUNCNAME฀(nome฀ ceber฀o฀nome฀de฀um฀comando,฀toda฀vez฀
uma฀pequena฀parte฀pode฀lhe฀ajudar฀na฀ da฀função฀em฀execução). que฀você฀teclar฀um฀[ENTER]฀sozinho฀no฀
elaboração฀de฀scripts.฀Veja฀a฀seguir฀as฀ LOGNAME฀»฀Esta฀variável฀armazena฀o฀ prompt฀principal฀($PS ),฀esse฀comando฀
principais฀delas: nome฀de฀login฀do฀usuário฀. será฀executado.฀É฀muito฀útil฀quando฀você฀
CDPATH฀ »฀ Contém฀ os฀ caminhos฀ que฀ MAILCHECK฀»฀Especifica,฀em฀segundos,฀a฀ precisa฀repetindo฀constantemente฀uma฀
serão฀pesquisados฀para฀tentar฀localizar฀ freqüência฀com฀que฀o฀Shell฀verifica฀a฀pre- determinada฀instrução.
um฀diretório฀especificado.฀Apesar฀dessa฀ sença฀de฀correspondência฀nos฀arquivos฀ PS ฀»฀É฀o฀prompt฀principal.฀No฀“Papo฀
variável฀ser฀pouco฀conhecida,฀seu฀uso฀ indicados฀pela฀variáveis฀ $MAILPATH฀ou฀ de฀Botequim”฀usamos฀os฀padrões฀$฀para฀
deve฀ser฀incentivado฀por฀poupar฀muito฀ $MAIL.฀O฀tempo฀padrão฀é฀de฀60฀segundos฀ usuário฀comum฀e฀ ฀para฀root,฀mas฀é฀mui-

junho฀2005฀ edição฀09 87
[Link]
Linux฀User Papo฀de฀Botequim

to฀freqüente฀que฀ele฀esteja฀personalizado.฀ Expansão de parâmetros $ cadeia= Pa de B e i


Uma฀curiosidade฀é฀que฀existe฀até฀concurso฀ Bem,฀muito฀do฀que฀vimos฀até฀agora฀são฀ $ ech ${cadeia * }
de฀quem฀programa฀o฀$PS ฀mais฀criativo. comandos฀externos฀ao฀Shell.฀Eles฀quebram฀ de B e i
PS ฀»฀Também฀chamado฀“prompt฀de฀ o฀maior฀galho,฀facilitam฀a฀visualização,฀ $ ech C e a ${cadeia * }
continuação”,฀é฀aquele฀sinal฀de฀maior฀ manutenção฀e฀depuração฀do฀código,฀mas฀ C e a de B e i
(>)฀que฀aparece฀após฀um฀[ENTER]฀sem฀ não฀são฀tão฀eficientes฀quanto฀os฀intrínse-
o฀comando฀ter฀sido฀encerrado. cos฀(built-ins).฀Quando฀o฀nosso฀problema฀ No฀exemplo฀anterior฀foi฀suprimido฀à฀
PWD฀ »฀ Possui฀ o฀ caminho฀ completo฀ for฀performance,฀devemos฀dar฀preferência฀ esquerda฀tudo฀o฀que฀“casa”฀com฀a฀menor฀
($PATH)฀ do฀ diretório฀ corrente.฀ Tem฀ o฀ ao฀uso฀dos฀intrínsecos.฀A฀partir฀de฀agora฀ ocorrência฀da฀expressão฀ * ,฀ou฀seja,฀
mesmo฀efeito฀do฀comando฀ d. vou฀te฀mostrar฀algumas฀técnicas฀para฀o฀ todos฀os฀caracteres฀até฀o฀primeiro฀espaço฀
RANDOM฀»฀Cada฀vez฀que฀esta฀variável฀é฀ seu฀programa฀pisar฀no฀acelerador. em฀branco.฀Esses฀exemplos฀também฀po-
acessada,฀devolve฀um฀inteiro฀aleatório฀en- Na฀tabela 3฀e฀nos฀exemplos฀a฀seguir,฀ deriam฀ser฀escritos฀sem฀proteger฀o฀espaço฀
tre฀0฀e฀32767.฀Para฀gerar฀um฀inteiro฀entre฀ veremos฀uma฀série฀de฀construções฀cha- da฀interpretação฀do฀Shell฀(mas฀prefiro฀
0฀e฀100,฀por฀exemplo,฀digitamos: madas฀expansão฀(ou฀substituição)฀de฀ protegê-lo฀para฀facilitar฀a฀legibilidade฀
parâmetros฀(Parameter฀Expansion),฀que฀ do฀código).฀Veja฀só:
$ ech $ RANDOM substituem฀instruções฀como฀o฀c ,฀o฀e ,฀
o฀ ,฀o฀ ed฀e฀outras฀de฀forma฀mais฀ágil. $ ech ${cadeia * }
Vamos฀ver฀alguns฀exemplos:฀se฀em฀uma฀ de B e i
Ou฀seja,฀pegamos฀o฀resto฀da฀divisão฀do฀ pergunta฀o฀ S฀é฀oferecido฀como฀valor฀de- $ ech C e a ${cadeia * }
número฀randômico฀gerado฀por฀101฀porque฀ fault฀(padrão)฀e฀a฀saída฀vai฀para฀a฀variável฀ C e a de B e i
o฀resto฀da฀divisão฀de฀qualquer฀número฀ SN,฀após฀ler฀o฀valor฀podemos฀fazer:
por฀101฀varia฀entre฀0฀e฀100. Repare฀que฀na฀construção฀de฀ e ฀é฀
REPLY฀»฀Use฀esta฀variável฀para฀recuperar฀ SN=$ SN:-S} permitido฀o฀uso฀de฀metacaracteres.
o฀último฀campo฀lido,฀caso฀ele฀não฀tenha฀ Utilizando฀o฀mesmo฀valor฀da฀variável฀
nenhuma฀variável฀associada.฀Exemplo: Para฀saber฀o฀tamanho฀de฀uma฀cadeia: cadeia,฀observe฀como฀faríamos฀para฀ter฀
somente฀B e i :
$ ead - Digi e S N: $ cadeia=
Digi e S N: N $ ech ${ cadeia} $ ech ${cadeia * }
$ ech $REPLY 4 B e i
N $ ech Va Ch ea ${cadeia * }
Para฀extrair฀dados฀de฀cadeia,฀da฀posi- Va Ch ea B e i
SECONDS฀»฀Esta฀variável฀informa,฀em฀se- ção฀um฀até฀o฀final฀fazemos:
gundos,฀há฀quanto฀tempo฀o฀Shell฀corrente฀ Desta฀vez฀suprimimos฀à฀esquerda฀de฀
está฀“de฀pé”.฀Use-a฀para฀demonstrar฀a฀ $ cadeia=abcdef cadeia฀a฀maior฀ocorrência฀da฀expressão฀
estabilidade฀do฀Linux฀e฀esnobar฀usuários฀ $ ech ${cadeia: } e .฀Assim฀como฀no฀caso฀anterior,฀o฀uso฀
daquela฀coisa฀com฀janelinhas฀coloridas฀ bcdef de฀metacaracteres฀é฀permitido.
que฀chamam฀de฀sistema฀operacional,฀mas฀ Outro฀exemplo฀mais฀útil:฀para฀que฀não฀
que฀necessita฀de฀“reboots”฀freqüentes. Repare฀que฀a฀origem฀é฀zero฀e฀não฀um.฀ apareça฀o฀caminho฀(path)฀completo฀do฀seu฀
TMOUT฀»฀Se฀esta฀variável฀contiver฀um฀ Vamos฀extrair฀3฀caracteres฀a฀partir฀da฀2ª฀ programa฀($ )฀em฀uma฀mensagem฀de฀erro,฀
valor฀ maior฀ do฀ que฀ zero,฀ esse฀ valor฀ posição฀da฀mesma฀variável฀cadeia: inicie฀o฀seu฀texto฀da฀seguinte฀forma:
será฀considerado฀o฀timeout฀padrão฀do฀
comando฀read.฀No฀prompt,฀esse฀valor฀ $ ech ${cadeia: : } ech U : ${ *} e da e age de e
é฀interpretado฀como฀o฀tempo฀de฀espera฀ cde
por฀uma฀ação฀antes฀de฀expirar฀a฀sessão.฀ Neste฀exemplo฀seria฀suprimido฀à฀es-
Supondo฀que฀a฀variável฀contenha฀o฀valor฀ Repare฀que฀novamente฀a฀origem฀da฀con- querda฀tudo฀até฀a฀última฀barra฀( )฀do฀
,฀o฀Shell฀encerrará฀a฀sessão฀do฀usuário฀ tagem฀é฀zero฀e฀não฀um.฀Para฀suprimir฀ caminho,฀restando฀somente฀o฀nome฀do฀
(ou฀seja,฀fará฀logout)฀após฀30฀segundos฀ tudo฀à฀esquerda฀da฀primeira฀ocorrência฀ programa.฀O฀caractere฀ ฀é฀simétrico฀ao฀
sem฀nenhuma฀ação฀no฀prompt. de฀uma฀cadeia,฀faça: ,฀veja฀o฀exemplo:

88 junho฀2005฀ edição฀09
[Link]
Papo฀de฀Botequim Linux฀User

Tabela 3: Tipos de expansão de parâmetros Há฀várias฀formas฀de฀trocar฀uma฀subca-


deia฀no฀início฀ou฀no฀fim฀de฀uma฀variável.฀
Expansão de parâmetros Resultado esperado
Para฀trocar฀no฀início฀fazemos:
${var:-padrao} Se a é vazia, o resultado da expressão é padrão
${#cadeia} Tamanho de $cadeia
${cadeia:posicao} Extrai uma subcadeia de $cadeia a partir de posição. Origem zero $ ech $Pa a
${cadeia:posicao:tamanho} Extrai uma subcadeia de $cadeia a partir de posição com tamanho e e
igual a a a h . Origem zero $ ech C di li a - ${Pa a U
${cadeia#expr} Corta a menor ocorrência de $cadeia à esquerda da expressão e e ã }
${cadeia##expr} Corta a maior ocorrência de $cadeia à esquerda da expressão e C di li a - ã e
${cadeia%expr} Corta a menor ocorrência de $cadeia à direita da expressão e
${cadeia%%expr} Corta a maior ocorrência de $cadeia à direita da expressão e
Para฀trocar฀no฀final฀fazemos:
${cadeia/subcad1/subcad2} Troca a primeira ocorrência de bcad por bcad
${cadeia//subcad1/subcad2} Troca todas as ocorrências de bcad por bcad
${cadeia/#subcad1/subcad2} Se bcad combina com o início de cadeia, então é trocado por bcad $ ech C di de i - U

${cadeia/%subcad1/subcad2} Se bcad combina com o fim de cadeia, então é trocado por bcad ${Pa a e ã }
C di de i - e ã

$ ech $cadeia $ ech ${cadeia * C e a} –฀฀A gora฀já฀chega,฀o฀papo฀hoje฀foi฀chato฀


Pa de B e i C e a de B e i porque฀teve฀muita฀decoreba,฀mas฀o฀que฀
$ ech ${cadeia *} $ ech ${cadeia C e a} mais฀importa฀é฀você฀ter฀entendido฀o฀
Pa de C e a de B e i que฀te฀falei.฀Quando฀precisar,฀consulte฀
$ ech ${cadeia *} estes฀guardanapos฀onde฀rabisquei฀as฀
Pa Trocando฀todas฀as฀ocorrências฀de฀uma฀ dicas฀e฀depois฀guarde-os฀para฀consultas฀
subcadeia฀por฀outra.฀O฀comando: futuras.฀Mas฀voltando฀à฀vaca฀fria:฀tá฀
Para฀trocar฀primeira฀ocorrência฀de฀uma฀ na฀hora฀de฀tomar฀outro฀e฀ver฀o฀jogo฀do฀
subcadeia฀em฀uma฀cadeia฀por฀outra: $ ech ${cadeia a} Mengão.฀Pra฀próxima฀vez฀vou฀te฀dar฀
Pa a de Ba e i moleza฀e฀só฀vou฀cobrar฀o฀seguinte:฀pe-
$ ech $cadeia gue฀a฀rotina฀ e g a f c฀(da฀qual฀
Pa de B e i Ordena฀a฀troca฀de฀todos฀as฀letras฀ ฀por฀ falamos฀no฀início฀do฀nosso฀bate-papo฀
$ ech ${cadeia de } a.฀Outro฀exemplo฀mais฀útil฀é฀para฀contar฀ de฀hoje,฀veja฀a฀listagem 1)฀e฀otimize-a฀
Pa B e i a฀quantidade฀de฀arquivos฀existentes฀no฀ para฀que฀a฀variável฀$SN฀receba฀o฀valor฀
$ ech ${cadeia de } diretório฀corrente.฀Observe฀o฀exemplo: padrão฀por฀expansão฀de฀parâmetros,฀
Pa B e i como฀vimos.
$ l | c -l E฀não฀se฀esqueça:฀em฀caso฀de฀dúvidas฀
Preste฀atenção฀quando฀for฀usar฀metaca- ou฀falta฀de฀companhia฀para฀um฀(ou฀mais)฀
racteres!฀Eles฀são฀gulosos฀e฀sempre฀com- chope฀é฀só฀mandar฀um฀e-mail฀para฀julio.
binarão฀com฀a฀maior฀possibilidade;฀No฀ O฀ c฀põe฀um฀monte฀de฀espaços฀em฀ neves@[Link].฀E฀diga฀para฀os฀amigos฀
exemplo฀a฀seguir฀eu฀queria฀trocar฀Papo฀de฀ branco฀antes฀do฀resultado.฀Para฀tirá-los: que฀quem฀estiver฀a฀fim฀de฀fazer฀um฀curso฀
Botequim฀por฀Conversa฀de฀Botequim: porreta฀de฀programação฀em฀Shell฀deve฀
Q dA ecebe a aída d c a d mandar฀um฀e-mail฀para฀[Link]@tecnohall.
$ ech $cadeia $ Q dA =$ l | c -l [Link]฀para฀informar-se.฀Valeu!฀ ■
Pa de B e i $ ech ${Q dA * }
$ ech ${cadeia * C e a} Julio Cezar Neves é Analista de Suporte de
Sobre฀o฀autor

C e a e i Sistemas desde 1969 e trabalha com Unix


Nesse฀exemplo,฀eu฀sabia฀que฀a฀saída฀era฀ desde 1980, quando participou do desen-
A฀idéia฀era฀pegar฀tudo฀até฀o฀primeiro฀ composta฀de฀brancos฀e฀números,฀por฀isso฀ volvimento do SOX, um sistema operacio-
,฀mas฀acabou฀sendo฀trocado฀tudo฀até฀o฀ montei฀essa฀expressão฀para฀trocar฀todos฀os฀ nal similar ao Unix produzido pela Cobra
último฀ .฀Isto฀poderia฀ser฀resolvido฀de฀ espaços฀por฀nada.฀Note฀que฀antes฀e฀após฀o฀ Computadores. Pode ser contatado no
diversas฀maneiras.฀Eis฀algumas: asterisco฀(*)฀há฀espaços฀em฀branco. e-mail [Link]@[Link]

junho฀2005฀ edição฀09 89
[Link]
Linux฀User Papo฀de฀Botequim

Papo฀de฀Botequim
Curso de Shell Script

Parte฀X

Dave Hamilton - [Link]


Em mais um capítulo de nossa saga através do mundo do
Shell Script, vamos aprender a avaliar expressões, capturar
sinais e receber parâmetros através da linha de comando.
por฀Júlio฀Cezar฀Neves

E
aê฀amigo,฀te฀dei฀a฀maior฀moleza฀na฀ a฀legibilidade฀do฀código฀está฀“horrorível”,฀ O comando eval
última฀aula฀né?฀Um฀exerciciozinho฀ mas฀o฀desempenho,฀isto฀é,฀a฀velocidade฀ V
฀ ou฀te฀dar฀um฀problema฀que฀eu฀duvido฀
muito฀simples…฀ de฀execução,฀está฀ótimo.฀Como฀funções฀ que฀você฀resolva:฀
฀–฀É,฀mas฀nos฀testes฀que฀eu฀fi฀z,฀e฀de฀ são฀coisas฀muito฀pessoais,฀já฀que฀cada฀
acordo฀com฀o฀que฀você฀ensinou฀sobre฀ um฀usa฀as฀suas฀e฀quase฀não฀há฀neces- $ a =
substituição฀de฀parâmetros,฀achei฀que฀ sidade฀de฀manutenção,฀eu฀sempre฀opto฀ $ a = a
deveria฀fazer฀algumas฀alterações฀nas฀fun- pelo฀desempenho.฀
ções฀que฀desenvolvemos฀para฀torná-las฀de฀ ฀Hoje฀vamos฀sair฀daquela฀chatura฀que฀ ฀Te฀dei฀essas฀duas฀variáveis฀e฀quero฀que฀
uso฀geral,฀como฀você฀disse฀que฀todas฀as฀ foi฀o฀nosso฀último฀papo฀e฀voltar฀à฀lógica,฀ você฀me฀diga฀como฀eu฀posso,฀me฀referindo฀
funções฀deveriam฀ser.฀Quer฀ver?฀ saindo฀da฀decoreba.฀Mas฀volto฀a฀te฀lem- apenas฀à฀variável฀a฀ a ,฀listar฀o฀valor฀de฀
฀–฀Claro,฀né,฀mané,฀se฀te฀pedi฀para฀fazer฀ brar:฀tudo฀que฀eu฀te฀mostrei฀da฀última฀vez฀ a ฀(que,฀no฀nosso฀caso,฀é฀3).฀
é฀porque฀estou฀a฀fi฀m฀de฀te฀ver฀aprender,฀ aqui฀no฀Boteco฀do฀Chico฀é฀válido฀e฀quebra฀ ฀–฀Ah,฀isso฀é฀mole,฀mole!฀É฀só฀digitar฀
mas฀peraí,฀dá฀um฀tempo.฀Chico!฀Manda฀ um฀galhão.฀Guarde฀aqueles฀guardanapos฀ esse฀comando฀aqui:฀
dois,฀um฀sem฀colarinho!฀Vai,฀mostra฀aí฀ que฀rabiscamos฀porque,฀mais฀cedo฀ou฀
o฀que฀você฀fez.฀ mais฀tarde,฀eles฀lhe฀vão฀ser฀muito฀úteis.฀ ech $`ech $ a `
฀–฀Bem,฀além฀do฀que฀você฀pediu,฀eu฀
reparei฀que฀o฀programa฀que฀chamava฀a฀ Listagem 1: função [Link]
função฀teria฀de฀ter฀previamente฀defi฀nidas฀ A f çã ecebe a â e a eg i e de :
a฀linha฀em฀que฀seria฀mostrada฀a฀mensa- $ - Me age a e ada a ela
gem฀e฀a฀quantidade฀de฀colunas.฀O฀que฀ $ - Val a e acei c e a ad ã
fi฀z฀foi฀incluir฀duas฀linhas฀–฀nas฀quais฀ 4 $ - O al acei
empreguei฀substituição฀de฀parâmetros฀ 5 S d e $ =Acei a , $ = e $ = , a li ha
–฀para฀que,฀caso฀uma฀dessas฀variáveis฀não฀ abai c l ca ia e M g al Acei a S
T C l =${T C l :-$ c l } Se ã e a a defi id , ag a e á
fosse฀informada,฀ela฀recebesse฀um฀valor฀
8 Li haMe g=${Li haMe g:-$ $ li e - } Ide
atribuído฀pela฀própria฀função.฀A฀linha฀
M g= $ `ech $ | a- A-Z` `ech $ | A-Z a- `
de฀mensagem฀é฀três฀linhas฀antes฀do฀fi฀m฀ Ta M g=${ M g}
da฀tela฀e฀o฀total฀de฀colunas฀é฀obtido฀pelo฀ C l=$ T C l - Ta M g Pa a ce ali a M g a li ha
comando฀ c l .฀Dê฀uma฀olhada฀na฀ c $Li haMe g $C l
listagem 1฀e฀veja฀como฀fi฀cou:฀ ead - - $M g SN
฀–฀Gostei,฀você฀já฀se฀antecipou฀ao฀que฀eu฀ 4 SN=${SN:-$ } Se a ia c l ca ad ã e SN
ia฀pedir.฀Só฀pra฀gente฀encerrar฀esse฀papo฀ 5 SN=$ ech $SN | A-Z a- A aída de SN e á e i c la
c $Li haMe g $C l el A aga M g da ela
de฀substituição฀de฀parâmetros,฀repare฀que฀

86 julho฀2005฀ edição฀10
[Link]
Papo฀de฀Botequim Linux฀User

Repare฀que฀eu฀coloquei฀o฀ech $ a ฀entre฀crases฀(`),฀porque฀ $ a =l
dessa฀forma฀ele฀terá฀prioridade฀de฀execução฀e฀resultará฀em฀ a .฀ $ $ a
E฀ech $ a ฀produzirá฀3… ag h al h i c l gad
–฀Ah,฀é?฀Então฀execute฀para฀ver฀se฀está฀correto. ag h A D DOS li a ica l ga e h
ag h c f li a i a a da g f c
$ ech $`ech $ a ` al h c al h li a i a bg h
$ a
Agora฀vamos฀colocar฀em฀ a ฀o฀seguinte:฀ l $ a ;฀e฀em฀
–฀Ué!฀Que฀foi฀que฀aconteceu?฀O฀meu฀raciocínio฀me฀parecia฀ a ฀vamos฀colocar฀l*,฀vejamos฀o฀resultado:
bastante฀lógico…
–฀O฀seu฀raciocínio฀realmente฀foi฀lógico,฀o฀problema฀é฀que฀você฀ $ a = l $ a
esqueceu฀de฀uma฀das฀primeiras฀coisas฀de฀que฀te฀falei฀aqui฀no฀ $ a = l*
Boteco฀e฀que฀vou฀repetir.฀O฀Shell฀usa฀a฀seguinte฀ordem฀para฀ $ $ a
resolver฀uma฀linha฀de฀comando: l : $ a : N ch file di ec
P฀Resolve฀os฀redirecionamentos; $ e al $ a
P฀Substitui฀as฀variáveis฀pelos฀seus฀valores; li a ica li a i a li a i a l gad l ga e h
P฀Resolve฀e฀substitui฀os฀meta฀caracteres;
P฀Passa฀a฀linha฀já฀toda฀esmiuçada฀para฀execução. Novamente,฀no฀tempo฀de฀substituição฀das฀variáveis,฀ $ a ฀
Dessa฀forma,฀quando฀o฀interpretador฀chegou฀na฀fase฀de฀re- ainda฀não฀havia฀se฀apresentado฀ao฀Shell฀para฀ser฀resolvida.฀
solução฀de฀variáveis,฀que฀como฀eu฀disse฀é฀anterior฀à฀execução,฀ Assim,฀só฀nos฀resta฀executar฀o฀comando฀eval฀para฀dar฀as฀duas฀
a฀única฀variável฀existente฀era฀ a ฀e฀por฀isso฀a฀tua฀solução฀ passadas฀necessárias.
produziu฀como฀saída฀$ a .฀O฀comando฀echo฀identificou฀isso฀ Uma฀vez฀u m฀colega฀da฀excelente฀l ista฀de฀d iscussão฀[Link]/
como฀uma฀cadeia฀de฀caracteres฀e฀não฀como฀uma฀variável. group/shell-script฀colocou฀uma฀dúvida:฀queria฀fazer฀um฀menu฀
Problemas฀desse฀tipo฀são฀relativamente฀freqüentes฀e฀seriam฀ que฀numerasse฀e฀listasse฀todos฀os฀arquivos฀com฀extensão฀ h฀e,฀
insolúveis฀caso฀não฀existisse฀a฀instrução฀eval,฀cuja฀sintaxe฀é฀ quando฀o฀operador฀escolhesse฀uma฀opção,฀o฀programa฀corres-
e al c d,฀onde฀ c d฀é฀uma฀linha฀de฀comando฀qualquer,฀que฀ pondente฀fosse฀executado.฀Veja฀minha฀proposta฀na฀listagem 2:
você฀poderia฀inclusive฀executar฀direto฀no฀prompt฀do฀terminal.฀
Quando฀você฀põe฀o฀eval฀na฀frente,฀no฀entanto,฀o฀que฀ocorre฀é฀ Listagem 2: [Link]
que฀o฀Shell฀trata฀c d฀como฀um฀parâmetro฀do฀eval฀e,฀em฀seguida,฀ ! bi ba h
o฀eval฀executa฀a฀linha฀recebida,฀submetendo-a฀ao฀Shell.฀Ou฀
seja,฀na฀prática฀ c d฀é฀analisado฀duas฀vezes.฀Dessa฀forma,฀se฀ Li a e e e a g a a c e e ã h
executássemos฀o฀comando฀que฀você฀propôs฀colocando฀o฀eval฀ 4 di e i c e e e e ec a e c lhid el e ad
5
na฀frente,฀teríamos฀a฀saída฀esperada.฀Veja:
clea i=
i f \ \ \ O çã P g a a
$ e al ech $`ech $ a ` 8 CASE= ca e $ i
f a i * h
d
Esse฀exemplo฀também฀poderia฀ter฀sido฀feito฀de฀outra฀maneira.฀ i f \ d\ \ $i $a
CASE= $CASE
Dá฀só฀uma฀olhada:
$ i f d \ $i $a
4 i=$ i
$ e al ech \$$ a 5 d e
CASE= $CASE
* e
Na฀primeira฀passada฀a฀contrabarra฀(\)฀seria฀retirada฀e฀$ a ฀ 8 e ac
ead - - I f e a çã de ejada:
seria฀resolvido฀produzindo฀ a .฀Na฀segunda฀passada฀teria฀so-
ech
brado฀ech $ a ,฀que฀produziria฀o฀resultado฀esperado.฀Agora฀ e al $CASE
vou฀colocar฀um฀comando฀dentro฀de฀ a ฀e฀executar:

julho฀2005฀ edição฀10 87
[Link]
Linux฀User Papo฀de฀Botequim

Parece฀complicado฀porque฀usei฀muitos฀ dos฀por)฀processos฀em฀execução.฀Vamos,฀ "limpar฀a฀área"฀ao฀seu฀término.฀Se฀seu฀


i f฀para฀formatação฀da฀tela,฀mas฀na฀ de฀agora฀em฀diante,฀dar฀uma฀olhadinha฀ encerramento฀ocorrer฀de฀forma฀prevista,฀
verdade฀é฀bastante฀simples:฀o฀primei- nos฀sinais฀enviados฀aos฀processos฀e฀mais฀ ou฀seja,฀se฀tiver฀um฀término฀normal,฀é฀
ro฀ i f฀foi฀colocado฀para฀imprimir฀ à฀frente฀vamos฀dar฀uma฀passada฀rápida฀ muito฀fácil฀fazer฀essa฀limpeza;฀porém,฀
o฀cabeçalho฀e฀logo฀em฀seguida฀come- pelos฀ sinais฀ gerados฀ pelos฀ processos.฀ se฀o฀seu฀programa฀tiver฀um฀fim฀brusco,฀
cei฀a฀montar฀dinamicamente฀a฀variável฀ Para฀mandar฀um฀sinal฀a฀um฀processo,฀ muita฀coisa฀ruim฀pode฀ocorrer:
$CASE,฀na฀qual฀ao฀final฀será฀feito฀um฀eval฀ usamos฀normalmente฀o฀comando฀kill,฀ P฀É฀possível฀que฀em฀um฀determinado฀es-
para฀execução฀do฀programa฀escolhido.฀ cuja฀sintaxe฀é: paço฀de฀tempo,฀o฀seu฀computador฀esteja฀
Repare฀no฀entanto฀que฀dentro฀do฀loop฀ cheio฀de฀arquivos฀de฀trabalho฀inúteis
do฀f ฀existem฀dois฀ i f:฀o฀primeiro฀ $ kill - ig PID P฀Seu฀processador฀poderá฀ficar฀atolado฀
serve฀para฀formatar฀a฀tela฀e฀o฀segundo฀ de฀processos฀zombies฀e฀defuncts฀gera-
para฀montar฀o฀ca e฀(se฀antes฀do฀coman- Onde฀ PID฀é฀o฀identificador฀do฀proces- dos฀por฀processos฀filhos฀que฀perderam฀
do฀ ead฀você฀colocar฀uma฀linha฀ ech so฀(Process฀Identification฀ou฀Process฀ID).฀ os฀pais฀e฀estão฀“órfãos”;
$CASE ,฀verá฀que฀o฀comando฀ca e฀mon- Além฀do฀comando฀kill,฀algumas฀seqüên- P฀É฀necessário฀liberar฀sockets฀abertos฀para฀
tado฀dentro฀da฀variável฀está฀todo฀inden- cias฀de฀teclas฀também฀podem฀gerar฀sinais.฀ não฀deixar฀os฀clientes฀congelados;
tado.฀Frescura,฀né?:).฀Na฀saída฀do฀f ,฀foi฀ A฀tabela 1฀mostra฀os฀sinais฀mais฀impor- P฀Seus฀bancos฀de฀dados฀poderão฀ficar฀
adicionada฀uma฀linha฀à฀variável฀ $CASE฀ tantes฀para฀monitorarmos: corrompidos฀porque฀sistemas฀gerencia-
para,฀no฀caso฀de฀uma฀escolha฀inválida,฀ Além฀desses,฀existe฀o฀famigerado฀si- dores฀de฀bancos฀de฀dados฀necessitam฀
ser฀executada฀uma฀função฀externa฀para฀ nal฀- ฀ou฀SIGKILL฀que,฀para฀o฀processo฀ de฀um฀tempo฀para฀gravar฀seus฀buffers฀
exibir฀mensagens฀de฀erro.฀Vamos฀execu- que฀o฀está฀recebendo,฀equivale฀a฀meter฀ em฀disco฀(commit).
tar฀o฀script฀para฀ver฀a฀saída฀gerada: o฀dedo฀no฀botão฀de฀desligar฀do฀compu- Enfim,฀existem฀mil฀razões฀para฀não฀usar฀
tador฀–฀o฀que฀é฀altamente฀indesejável,฀ um฀kill฀com฀o฀sinal฀- ฀e฀para฀monitorar฀o฀
$ fa e h já฀que฀muitos฀programas฀necessitam฀ encerramento฀anormal฀de฀programas.
O ca P g a a
Listagem 3: Nova versão do [Link]
ag h
! bi ba h
ag h
ag h Li a e e a d g a a c e e ã h
4 al h 4 di e i c e e e ec a e c lhid el e ad
5 al h 5
c al h clea i=
fa e h i f \ \ \ O çã P g a a
8 l ga e h 8 CASE= ca e $ i
bg h f a i * h
ead i e h d
edi ead h i f \ d\ \ $i $a
I f e a çã de ejada: CASE= $CASE
$ i f d \ $i $a
Seria฀interessante฀incluir฀uma฀opção฀ 4 i=$ i
para฀terminar฀o฀programa฀e,฀para฀isso,฀ 5 d e
seria฀necessária฀a฀inclusão฀de฀uma฀linha฀ i f \ d\ \ \ Fi d g a a Li ha i cl ída
após฀o฀loop฀de฀montagem฀da฀tela฀e฀a฀alte- CASE= $CASE

ração฀da฀linha฀na฀qual฀fazemos฀a฀atribui- 8 e i Li ha al e ada

ção฀final฀do฀valor฀da฀variável฀$CASE.฀Veja฀ * e
e ac
na฀listagem 3฀como฀ele฀ficaria:
ead - - I f e a çã de ejada:
Existe฀no฀Linux฀uma฀coisa฀chamada฀
ech
sinal฀( ig al).฀Existem฀diversos฀sinais฀
e al $CASE
que฀podem฀ser฀mandados฀para฀(ou฀gera-

88 julho฀2005฀ edição฀10
[Link]
Papo฀de฀Botequim Linux฀User

O comando trap Caso฀a฀transferência฀seja฀interrompida฀ Tabela 1: Principais sinais


Para฀fazer฀a฀monitoração฀de฀sinais฀existe฀ por฀um฀kill฀ou฀um฀[CTRL]+[C],฀certa-
Código Nome Gerado por:
o฀comando฀ a ,฀cuja฀sintaxe฀pode฀ser฀ mente฀deixará฀lixo฀no฀disco.฀É฀exatamen-
0 EXIT Fim normal do programa
uma฀das฀mostradas฀a฀seguir: te฀essa฀a฀forma฀mais฀comum฀de฀uso฀do฀ 1 SIGHUP Quando o programa
comando฀ a .฀Como฀isso฀é฀trecho฀de฀ recebe um kill -HUP
a c d c d c d S S … SN um฀script฀devemos,฀logo฀no฀início฀dele,฀ 2 SIGINT Interrupção pelo teclado.
a c d c d c d S S … SN digitar฀o฀comando:฀ ([CTRL]+[C])
3 SIGQUIT Interrupção pelo teclado
([CTRL]+[\])
Onde฀os฀comandos฀฀c d , c d , c d ฀ a -f $$ e i 5
15 SIGTERM Quando o programa
serão฀executados฀caso฀o฀programa฀receba฀ recebe um kill ou
os฀sinais฀S , S ฀…฀SN.฀As฀aspas฀( )฀ou฀ Dessa฀forma,฀caso฀houvesse฀uma฀inter- kill -TERM
as฀apóstrofes฀( )฀só฀são฀necessárias฀caso฀ rupção฀brusca฀(sinais฀1,฀2฀,฀3฀ou฀15)฀antes฀
o฀trap฀possua฀mais฀de฀um฀comando฀c d฀ do฀programa฀encerrar฀(no฀e i ฀dentro฀do฀
associado.฀Cada฀uma฀delas฀pode฀ser฀tam- comando฀ a ),฀ou฀um฀fim฀normal฀(sinal฀ 1º Caso:฀O฀comando฀ f ฀encontra-se฀
bém฀uma฀função฀interna,฀uma฀externa฀ 0),฀o฀arquivo฀ $$฀seria฀removido. em฀ c i .฀Nesse฀caso,฀o฀argumento฀do฀
ou฀outro฀script. Caso฀não฀houvesse฀a฀instrução฀ e i ฀ comando฀trap฀deveria฀vir฀entre฀aspas฀( )฀
Para฀entender฀o฀uso฀de฀aspas฀( )฀e฀ na฀linha฀de฀comando฀do฀ a ,฀ao฀final฀ porque,฀caso฀ocorresse฀uma฀interrupção฀
apóstrofes฀ ( )฀ vamos฀ recorrer฀ a฀ um฀ da฀execução฀dessa฀linha฀o฀fluxo฀do฀pro- ([CTRL]+[C]฀ou฀[CTRL]+[\])฀no฀ c i ,฀
exemplo฀ que฀ trata฀ um฀ fragmento฀ de฀ grama฀retornaria฀ao฀ponto฀em฀que฀estava฀ a฀linha฀só฀seria฀interpretada฀nesse฀mo-
um฀script฀que฀faz฀uma฀transferência฀de฀ quando฀recebeu฀o฀sinal฀que฀originou฀a฀ mento฀e฀o฀PID฀do฀ c i ฀seria฀diferente฀
arquivos฀via฀FTP฀para฀uma฀máquina฀ execução฀desse฀ a . do฀encontrado฀em฀ $$฀(não฀esqueça฀
remota฀($Re C ),฀na฀qual฀o฀usuário฀ Note฀também฀que฀o฀Shell฀pesquisa฀a฀ que฀$$฀é฀a฀variável฀que฀contém฀o฀PID฀do฀
é฀ $F la ,฀sua฀senha฀é฀ $Seg ed ฀e฀o฀ linha฀de฀comando฀uma฀vez฀quando฀o฀ a ฀ processo฀ativo);
arquivo฀a฀ser฀enviado฀é฀ $A .฀Suponha฀ é฀interpretado฀(e฀é฀por฀isso฀que฀é฀usual฀ 2º Caso:฀O฀comando฀ f ฀encontra-se฀
ainda฀que฀essas฀quatro฀variáveis฀foram฀ colocá-lo฀no฀início฀do฀programa)฀e฀nova- em฀ c i .฀Nesse฀caso,฀o฀argumento฀
recebidas฀por฀uma฀rotina฀anterior฀de฀ mente฀quando฀um฀dos฀sinais฀listados฀é฀ do฀comando฀ a ฀deveria฀estar฀entre฀
leitura฀e฀que฀esse฀script฀seja฀muito฀usado฀ recebido.฀Então,฀no฀último฀exemplo,฀o฀va- apóstrofes฀( ),฀pois฀caso฀a฀interrupção฀
por฀diversas฀pessoas.฀Vejamos฀o฀trecho฀ lor฀de฀$$฀será฀substituído฀no฀momento฀em฀ se฀desse฀durante฀a฀execução฀de฀ c i ,฀
de฀código฀a฀seguir: que฀o฀comando฀ a ฀é฀lido฀pela฀primeira฀ o฀arquivo฀não฀teria฀sido฀criado;฀caso฀ela฀
vez,฀já฀que฀as฀aspas฀( )฀não฀protegem฀o฀ ocorresse฀durante฀a฀execução฀de฀ c i ,฀
f -i $Re C << Fi FTP >> $$ U cifrão฀($)฀da฀interpretação฀do฀Shell. o฀valor฀de฀$$฀seria฀o฀PID฀desse฀processo,฀
>> $$ Se฀você฀quisesse฀fazer฀a฀substituição฀ que฀coincidiria฀com฀o฀de฀ $$.
e $F la $Seg ed somente฀ao฀receber฀o฀sinal,฀o฀comando฀ O฀comando฀ a ,฀quando฀executado฀
bi a deveria฀ser฀colocado฀entre฀apóstrofes฀( ).฀ sem฀argumentos,฀lista฀os฀sinais฀que฀estão฀
ge $A Assim,฀na฀primeira฀interpretação฀do฀ a ,฀ sendo฀monitorados฀no฀ambiente,฀bem฀
Fi FTP o฀Shell฀não฀veria฀o฀cifrão฀($),฀as฀apóstro- como฀a฀linha฀de฀comando฀que฀será฀exe-
fes฀( )฀seriam฀removidas฀e,฀finalmente,฀o฀ cutada฀quando฀tais฀sinais฀forem฀recebidos.฀
Repare฀que฀tanto฀as฀saídas฀dos฀diálo- Shell฀poderia฀substituir฀o฀valor฀da฀variá- Se฀a฀linha฀de฀comandos฀do฀ a ฀for฀nula฀
gos฀do฀FTP฀como฀os฀erros฀encontrados฀ vel.฀Nesse฀caso,฀a฀linha฀ficaria฀assim: (vazia),฀isso฀significa฀que฀os฀sinais฀espe-
estão฀sendo฀redirecionados฀para฀ $$,฀ cificados฀devem฀ser฀ignorados฀quando฀
o฀que฀é฀uma฀construção฀bastante฀comum฀ a -f $$ e i 5 recebidos.฀Por฀exemplo,฀o฀comando฀ a
para฀arquivos฀temporários฀usados฀em฀ ฀especifica฀que฀o฀sinal฀de฀interrup-
scripts฀com฀mais฀de฀um฀usuário,฀porque฀ Suponha฀ dois฀ casos:฀ você฀ tem฀ dois฀ ção฀([CTRL]+[C])฀deve฀ser฀ignorado.฀No฀
$$฀é฀a฀variável฀que฀contém฀o฀número฀do฀ scripts฀que฀chamaremos฀de฀ c i ,฀cuja฀ último฀exemplo,฀note฀que฀o฀primeiro฀ar-
processo฀(PID),฀que฀é฀único.฀Com฀esse฀ primeira฀linha฀será฀um฀ a ,฀e฀ c i ,฀ gumento฀deve฀ser฀especificado฀para฀que฀o฀
tipo฀de฀construção฀evita-se฀que฀dois฀ou฀ colocado฀em฀execução฀por฀ c i .฀Por฀ sinal฀seja฀ignorado฀e฀não฀é฀equivalente฀a฀
mais฀usuários฀disputem฀a฀posse฀e฀os฀di- serem฀dois฀processos฀diferentes,฀terão฀ escrever฀ a ,฀cuja฀finalidade฀é฀retornar฀
reitos฀sobre฀um฀arquivo. dois฀PIDs฀distintos. o฀sinal฀ ฀ao฀seu฀estado฀padrão.฀ ➟

julho฀2005฀ edição฀10 89
[Link]
Linux฀User Papo฀de฀Botequim

Se฀você฀ignorar฀um฀sinal,฀todos฀os฀sub- Para฀terminar฀esse฀assunto,฀abra฀um฀ cadeiade c e ฀deve฀ser฀ abc.฀Se฀você฀


shells฀irão฀ignorá-lo.฀Portanto,฀se฀você฀ console฀gráfico฀e฀escreva฀no฀prompt฀de฀ desejar฀que฀uma฀opção฀seja฀seguida฀por฀
especificar฀qual฀ação฀deve฀ser฀tomada฀ comando฀o฀seguinte: um฀argumento,฀ponha฀um฀sinal฀de฀dois฀
quando฀receber฀um฀sinal,฀todos฀os฀sub- pontos฀(:)฀depois฀da฀letra,฀como฀em฀a:bc.฀
shells฀irão฀tomar฀a฀mesma฀ação฀quando฀ $ a ech M d a a h da ja ela 8 Isso฀diz฀ao฀getopts฀que฀a฀opção฀-a฀tem฀a฀
receberem฀esse฀sinal.฀Ou฀seja,฀os฀sinais฀ forma฀-a a g e .฀Normalmente฀um฀
são฀automaticamente฀exportados.฀Para฀o฀ Em฀seguida,฀pegue฀o฀mouse฀e฀arraste-o฀ ou฀mais฀espaços฀em฀branco฀separam฀o฀
sinal฀mostrado฀(sinal฀2),฀isso฀significa฀que฀ de฀forma฀a฀variar฀o฀tamanho฀da฀janela฀ parâmetro฀da฀opção;฀no฀entanto,฀getopts฀
os฀sub-shells฀serão฀encerrados.฀Suponha฀ corrente.฀Surpreso?฀É฀o฀Shell฀orientado฀ também฀manipula฀parâmetros฀que฀vêm฀
que฀você฀execute฀o฀comando฀ a ฀e฀ a฀eventos…฀Mais฀unzinho,฀porque฀não฀ colados฀à฀opção฀como฀em฀ -aa g e .฀
então฀execute฀um฀sub-shell,฀que฀tornará฀a฀ consigo฀resistir.฀Escreva฀isto: cadeiade c e ฀não฀pode฀conter฀um฀si-
executar฀outro฀script฀como฀um฀sub-shell.฀ nal฀de฀interrogação฀( ).
Se฀for฀gerado฀um฀sinal฀de฀interrupção,฀ $ a ech já e a O฀nome฀constante฀da฀linha฀de฀sintaxe฀
este฀não฀terá฀efeito฀nem฀sobre฀o฀Shell฀ acima฀define฀uma฀variável฀que฀receberá,฀
principal฀nem฀sobre฀os฀sub-shell฀por฀ele฀ Em฀seguida฀digite: a฀cada฀vez฀que฀o฀comando฀getopts฀for฀
chamados,฀já฀que฀todos฀eles฀ignorarão฀ executado,฀o฀próximo฀dos฀parâmetros฀
o฀sinal. $ lee & posicionais฀e฀o฀colocará฀na฀variável฀ e.฀
Em฀korn฀shell฀(ksh)฀não฀existe฀a฀opção฀ getopts฀coloca฀uma฀interrogação฀( )฀na฀
- ฀do฀comando฀ ead฀para฀ler฀uma฀senha.฀ Você฀acabou฀de฀criar฀um฀sub-shell฀que฀ variável฀definida฀em฀nome฀se฀achar฀uma฀
O฀que฀costumamos฀fazer฀é฀usar฀usar฀o฀ irá฀ dormir฀ durante฀ três฀ segundos฀ em฀ opção฀não฀definida฀em฀cadeiade c e ฀
comando฀ ฀com฀a฀opção฀ -ech ,฀que฀ background.฀Ao฀fim฀desse฀tempo,฀você฀ ou฀se฀não฀achar฀o฀argumento฀esperado฀
inibe฀a฀escrita฀na฀tela฀até฀que฀se฀encon- receberá฀a฀mensagem฀“já฀era”,฀porque฀o฀ para฀uma฀determinada฀opção.
tre฀um฀ ech ฀para฀restaurar฀essa฀ sinal฀17฀é฀emitido฀a฀cada฀vez฀em฀que฀um฀ Como฀já฀sabemos,฀cada฀opção฀passada฀
escrita.฀Então,฀se฀estivéssemos฀usando฀o฀ sub-shell฀termina฀a฀sua฀execução.฀Para฀ por฀uma฀linha฀de฀comandos฀tem฀um฀ín-
interpretador฀ksh,฀a฀leitura฀da฀senha฀teria฀ devolver฀esses฀sinais฀ao฀seu฀comporta- dice฀numérico;฀assim,฀a฀primeira฀opção฀
que฀ser฀feita฀da฀seguinte฀forma: mento฀padrão,฀digite:฀ a 8. estará฀contida฀em฀$ ,฀a฀segunda฀em฀$ ฀e฀
Muito฀legal฀esse฀comando,฀né?฀Se฀você฀ assim฀por฀diante.฀Quando฀o฀getopts฀obtém฀
ech - Se ha: descobrir฀algum฀material฀bacana฀sobre฀ uma฀opção,฀ele฀armazena฀o฀índice฀do฀
-ech uso฀de฀sinais,฀por฀favor฀me฀informe฀por฀ próximo฀parâmetro฀a฀ser฀processado฀na฀
ead Se ha email,฀porque฀é฀muito฀rara฀a฀literatura฀ variável฀OPTIND
ech sobre฀o฀assunto. Quando฀uma฀opção฀tem฀um฀argumento฀
associado฀(indicado฀pelo฀:฀na฀cadeiade-
O฀problema฀com฀esse฀tipo฀de฀constru- Comando getopts c e ),฀getopts฀armazena฀o฀argumento฀
ção฀é฀que,฀caso฀o฀operador฀não฀soubes- O฀comando฀getopts฀recupera฀as฀opções฀e฀ na฀variável฀ OPTARG.฀Se฀uma฀opção฀não฀
se฀a฀senha,฀ele฀provavelmente฀teclaria฀ seus฀argumentos฀de฀uma฀lista฀de฀parâ- possuir฀argumento฀ou฀se฀o฀argumento฀
[CTRL]+[C]฀ou฀um฀[CTRL]+[\]฀durante฀ metros฀de฀acordo฀com฀a฀sintaxe฀POSIX.2,฀ esperado฀não฀for฀encontrado,฀a฀variável฀
a฀instrução฀ ead฀para฀descontinuar฀o฀pro- isto฀é,฀letras฀(ou฀números)฀após฀um฀sinal฀ OPTARG฀será฀"apagada"฀(com฀ e ).฀O฀co-
grama฀e,฀caso฀agisse฀dessa฀forma,฀o฀seu฀ de฀menos฀(-)฀seguidas฀ou฀não฀de฀um฀ mando฀encerra฀sua฀execução฀quando:
terminal฀estaria฀sem฀echo.฀Para฀evitar฀que฀ argumento;฀no฀caso฀de฀somente฀letras฀ P฀Encontra฀um฀parâmetro฀que฀não฀come-
isso฀aconteça,฀o฀melhor฀a฀fazer฀é: (ou฀números),฀elas฀podem฀ser฀agrupa- ça฀com฀um฀hífen฀(-).
das.฀Você฀deve฀usar฀esse฀comando฀para฀ P฀O฀parâmetro฀especial฀--฀indica฀o฀fim฀
ech - Se ha: "fatiar"฀opções฀e฀argumentos฀passados฀ das฀opções.
a ech para฀o฀seu฀script. P฀Quando฀encontra฀um฀erro฀(por฀exemplo,฀
e i A฀sintaxe฀é฀ge cadeiade c e uma฀opção฀não฀reconhecida).
-ech e.฀A฀cadeiade c e ฀deve฀explicitar฀ O฀exemplo฀da฀listagem 4฀é฀meramente฀
ead Se ha uma฀cadeia฀de฀caracteres฀com฀todas฀as฀ didático,฀servindo฀para฀mostrar,฀em฀um฀
ech opções฀reconhecidas฀pelo฀script;฀assim,฀ pequeno฀fragmento฀de฀código,฀o฀uso฀ple-
a se฀ele฀reconhece฀as฀opções฀ -a -b฀e฀ –c,฀ no฀do฀comando.

90 julho฀2005฀ edição฀10
[Link]
Papo฀de฀Botequim Linux฀User

Para฀entender฀melhor,฀vamos฀executar฀o฀script: OPTARG eh i e a
Di e a d i ei $OPTIND- = a g e
$ ge h -h -Pi e a a a O e b da li ha de c a d f i a a
ge fe a a ia el OPT LETRA ig al a h
OPTARG eh Repare,฀no฀exemplo฀a฀seguir,฀que฀se฀passarmos฀uma฀opção฀inválida฀a฀
ge fe a a ia el OPT LETRA ig al a P variável฀$OPT LETRA฀receberá฀um฀ponto฀de฀interrogação฀( )฀e฀a฀$OPTARG฀
OPTARG eh i e a será฀"apagada"฀( e ).
Di e a d i ei $OPTIND- = a g e
O e b da li ha de c a d f i a a $ ge h -f -Pi e a a a A çã –f ã é alida
ge h: illegal i -- f
Dessa฀forma,฀sem฀ter฀muito฀trabalho,฀separei฀ ge fe a a ia el OPT LETRA ig al a
todas฀as฀opções฀com฀seus฀respectivos฀argumentos,฀ OPTARG eh
deixando฀somente฀os฀parâmetros฀que฀foram฀passa- ge fe a a ia el OPT LETRA ig al a P
dos฀pelo฀operador฀para฀posterior฀tratamento.฀Repare฀ OPTARG eh i e a
que,฀se฀tivéssemos฀escrito฀a฀linha฀de฀comando฀com฀ Di e a d i ei $OPTIND- = a g e
o฀argumento฀(i e a)฀separado฀da฀opção฀(-P),฀ O e b da li ha de c a d f i a a
o฀resultado฀seria฀exatamente฀o฀mesmo,฀exceto฀pelo฀
OPTIND,฀já฀que฀nesse฀caso฀ele฀identifica฀um฀conjun- –฀Me฀diz฀uma฀coisa:฀você฀não฀poderia฀ter฀usado฀um฀condicional฀com฀
to฀de฀três฀opções฀(ou฀argumentos)฀e,฀no฀anterior,฀ case฀para฀evitar฀o฀getopts?
somente฀dois.฀Veja฀só: –฀Poderia฀sim,฀mas฀para฀quê?฀Os฀comandos฀estão฀aí฀para฀serem฀usados…฀
O฀exemplo฀foi฀didático,฀mas฀imagine฀um฀programa฀que฀aceitasse฀muitas฀
$ ge h -h -P i e a a a opções฀e฀cujos฀parâmetros฀poderiam฀ou฀não฀estar฀colados฀às฀opções,฀sen-
ge fe a a ia el OPT LETRA ig al a h do฀que฀as฀opções฀também฀poderiam฀ou฀não฀estar฀coladas:฀ia฀ser฀um฀case฀
OPTARG eh infernal!฀Com฀getopts,฀é฀só฀seguir฀os฀passos฀acima.
ge fe a a ia el OPT LETRA ig al a P –฀É…฀Vendo฀dessa฀forma,฀acho฀que฀você฀tem฀razão.฀É฀porque฀eu฀já฀estou฀
meio฀cansado฀com฀tanta฀informação฀nova฀na฀minha฀
Listagem 4: [Link] cabeça.฀Vamos฀tomar฀a฀saideira฀ou฀você฀ainda฀quer฀
$ ca ge h explicar฀alguma฀particularidade฀do฀Shell?
! bi h –฀Nem฀um฀nem฀outro,฀eu฀também฀já฀cansei฀mas฀
hoje฀não฀vou฀tomar฀a฀saideira฀porque฀estou฀indo฀
4 E ec e a i : dar฀aula฀na฀UniRIO,฀que฀é฀a฀primeira฀universidade฀
5 federal฀que฀está฀preparando฀seus฀alunos฀do฀curso฀
ge h -h -Pi e a a a de฀graduação฀em฀Informática฀para฀o฀uso฀de฀Soft-
ware฀Livre.฀Mas฀antes฀vou฀te฀deixar฀um฀problema฀
8 e e e a i f aç e de da a ç e ã e ibida
para฀te฀encucar:฀quando฀você฀varia฀o฀tamanho฀de฀
A cadeia P:h di e a çã -P é a çã c le a uma฀janela฀do฀terminal,฀no฀centro฀dela฀não฀aparece฀
e e e a g e e e h é a çã i le e ã e e dinamicamente,฀em฀vídeo฀reverso,฀a฀quantidade฀de฀
a g e linhas฀e฀colunas?฀Então!฀Eu฀quero฀que฀você฀repro-
duza฀isso฀usando฀a฀linguagem฀Shell.฀Chico,฀traz฀
4 hile ge P:h OPT LETRA rapidinho฀a฀minha฀conta!฀Vou฀contar฀até฀um฀e฀se฀
5 d você฀não฀trouxer฀eu฀me฀mando!
ech ge fe a a ia el OPT LETRA ig al a $OPT LETRA
Não฀se฀esqueça,฀qualquer฀dúvida฀ou฀falta฀de฀compa-
ech OPTARG eh $OPTARG
nhia฀para฀um฀chope฀é฀só฀mandar฀um฀email฀para฀julio.
8 d e
ed =`e $OPTIND – `
neves@[Link].฀Vou฀aproveitar฀também฀para฀mandar฀
ech Di e a d i ei \$OPTIND- = $ ed a g e o฀meu฀jabá:฀diga฀para฀os฀amigos฀que฀quem฀estiver฀a฀
hif $ ed fim฀de฀fazer฀um฀curso฀porreta฀de฀programação฀em฀
ech O e b da li ha de c a d f i $* Shell฀que฀mande฀um฀e-mail฀para฀[Link]@tecnohall.
[Link]฀para฀informar-se.฀Valeu!฀ ■

julho฀2005฀ edição฀10 91
[Link]
Linux฀User Papo฀de฀Botequim

Papo฀de฀botequim
Curso de Shell Script

Dave Hamilton - [Link]


Parte฀fi฀nal
A conversa está boa, mas uma hora eles tem que sair do bar. Na última
parte do nosso papo, falamos sobre pipes e sincronização entre processos.
por฀Júlio฀Cezar฀Neves

E
aí฀rapaz,฀tudo฀bom?฀ ฀–฀Não฀estou฀nem฀aí฀para฀a฀aparência,฀o฀que฀eu฀queria฀é฀que฀
฀–฀Beleza.฀Você฀se฀lembra฀de฀que฀da฀última฀vez฀você฀me฀ você฀exercitasse฀o฀que฀aprendemos.฀Me฀dá฀a฀listagem 1 ฀pra฀eu฀
pediu฀para฀fazer฀um฀programa฀que฀imprimisse฀dinami- ver฀o฀que฀você฀fez.฀
camente,฀no฀centro฀da฀tela,฀a฀quantidade฀de฀linhas฀e฀colunas฀ ฀–฀Perfeito!฀Que฀se฀dane฀a฀aparência,฀depois฀vou฀te฀ensinar฀
de฀um฀terminal฀sempre฀que฀o฀tamanho฀da฀janela฀variasse?฀ uns฀macetes฀para฀melhorá-la.฀O฀que฀vale฀é฀que฀o฀programa฀está฀
Pois฀é,฀eu฀até฀que฀fi฀z,฀mas฀mesmo฀depois฀de฀quebrar฀muito฀a฀ funcionando฀e฀está฀bem฀enxuto.฀
cabeça฀a฀aparência฀não฀fi฀cou฀igual.฀ ฀–฀Pôxa,฀e฀eu฀que฀perdi฀o฀maior฀tempo฀tentando฀descobrir฀
como฀aumentar฀a฀fonte…฀
Listagem 1: [Link] ฀–฀Deixe฀isso฀para฀lá!฀Hoje฀vamos฀ver฀umas฀coisas฀
! bi ba h bastante฀interessantes฀e฀úteis.฀

C l ca ce da ela, e ide e e , Dando nomes aos canos


4 a a idade de c l a e li ha ฀ m฀outro฀tipo฀de฀pipe฀é฀o฀฀named฀pipe฀,฀que฀também฀
U
5 a d a a h da ela eh al e ad é฀chamado฀de฀FIFO.฀FIFO฀é฀um฀acrônimo฀de฀฀First฀In฀
First฀Out฀฀que฀se฀refere฀à฀propriedade฀em฀que฀a฀ordem฀
a M da 8 8 = i al ge ad ela da ca a a h
dos฀bytes฀entrando฀no฀pipe฀é฀a฀mesma฀que฀a฀da฀saída.฀
8 da ela e M da eh a f ca e fa a i
O฀฀name฀฀em฀named฀pipe฀é,฀na฀verdade,฀o฀nome฀de฀um฀
B ld=$ b ld M d de e fa e arquivo.฀Os฀arquivos฀tipo฀named฀pipes฀são฀exibidos฀
Re =$ e M d de ide e e pelo฀comando฀฀ls฀฀como฀qualquer฀outro,฀com฀poucas฀
N =$ g Re a a a ela a ad a defa l diferenças,฀veja:฀

4 M da $ l -l i e
5 { - - -- j li di a Ja : i e |
clea
C l =$ c l
฀o฀ ฀na฀coluna฀mais฀à฀esquerda฀indica฀que฀ fif ฀
8 Li =$ li e
c $ $Li $ C l - Ce da ela
é฀um฀named฀pipe.฀O฀resto฀dos฀bits฀de฀controle฀de฀
ech $B ld$Re $C l X $Li $N permissões,฀quem฀pode฀ler฀ou฀gravar฀o฀pipe,฀funcio-
} nam฀como฀um฀arquivo฀normal.฀Nos฀sistemas฀mais฀
modernos฀uma฀barra฀vertical฀(|),฀ou฀pipe,฀no฀fi฀m฀do฀
clea nome฀do฀arquivo฀é฀outra฀dica฀e,฀nos฀sistemas฀LINUX,฀
4 ead - - M de a a h da ela ecle alg a a e i a onde฀o฀ l ฀pode฀exibir฀cores,฀o฀nome฀do฀arquivo฀é฀
escrito฀em฀vermelho฀por฀padrão.฀

86 agosto฀2005฀ edição฀11
[Link]
Papo฀de฀Botequim Linux฀User

Nos฀sistemas฀mais฀antigos,฀os฀named฀pipes฀são฀criados฀pelo฀ Sincronização de processos


utilitário฀mknod,฀normalmente฀situado฀no฀diretório฀ e c.฀Nos฀ Suponha฀que฀você฀dispare฀paralelamente฀dois฀programas฀(pro-
sistemas฀mais฀modernos,฀a฀mesma฀tarefa฀é฀feita฀pelo฀mkfifo,฀ cessos),฀chamados฀programa1฀e฀programa2,฀cujos฀diagramas฀de฀
que฀recebe฀um฀ou฀mais฀nomes฀como฀argumento฀e฀cria฀pipes฀ blocos฀de฀suas฀rotinas฀são฀como฀mostrado฀na฀tabela 1.฀Os฀dois฀
com฀esses฀nomes.฀Por฀exemplo,฀para฀criar฀um฀named฀pipe฀com฀ processos฀são฀disparados฀em฀paralelo฀e,฀no฀bloco฀1฀do฀programa1,฀
o฀nome฀ i e ,฀digite: as฀três฀classificações฀são฀disparadas฀da฀seguinte฀maneira:

$ kfif i e f A i BigFile BigFile BigFile


d
Como฀sempre,฀a฀melhor฀forma฀de฀mostrar฀como฀algo฀funciona฀ if $A
é฀dando฀exemplos.฀Suponha฀que฀nós฀tenhamos฀criado฀o฀named฀ he
pipe฀mostrado฀anteriormente.฀Vamos฀agora฀trabalhar฀com฀duas฀ Ma da= a
sessões฀ou฀dois฀consoles฀virtuais.฀Em฀um฀deles฀digite: el e
Ma da= a e
$ l -l > i e b eak
fi
e฀em฀outro฀faça: d e
ech $Ma da > i e
$ ca < i e [ $Ma da = a e ] &&
{
Voilà!฀A฀saída฀do฀comando฀executado฀no฀primeiro฀console฀ ech E d a e a cla ificaçã d a i
foi฀exibida฀no฀segundo.฀Note฀que฀a฀ordem฀em฀que฀os฀comandos฀ e i
ocorreram฀não฀importa. }
Se฀você฀prestou฀atenção,฀reparou฀que฀o฀primeiro฀comando฀ …
executado฀parecia฀ter฀"pendurado".฀Isto฀acontece฀porque฀a฀outra฀
ponta฀do฀pipe฀ainda฀não฀estava฀conectada,฀e฀então฀o฀sistema฀ Assim฀sendo,฀o฀comando฀if฀testa฀cada฀classificação฀que฀está฀
operacional฀suspendeu฀o฀primeiro฀processo฀até฀que฀o฀segundo฀ sendo฀efetuada.฀Caso฀ocorra฀qualquer฀problema,฀as฀classificações฀
"abrisse"฀o฀pipe.฀Para฀que฀um฀processo฀que฀usa฀pipe฀não฀fique฀ seguintes฀serão฀abortadas,฀uma฀mensagem฀contendo฀a฀string฀
em฀modo฀de฀espera,฀é฀necessário฀que฀em฀uma฀ponta฀do฀pipe฀ a e฀é฀enviada฀pelo฀pipe1฀e฀programa1฀é฀descontinuado฀com฀
haja฀um฀processo฀"falante"฀e฀na฀outra฀um฀"ouvinte".฀No฀exemplo฀ código฀de฀saída฀sinalizando฀um฀encerramento฀anormal.
anterior,฀o฀l ฀era฀o฀"falante"฀e฀o฀ca ฀era฀o฀"ouvinte". Enquanto฀o฀programa1฀executava฀o฀seu฀primeiro฀bloco฀(as฀
Um฀uso฀muito฀útil฀dos฀named฀pipes฀é฀permitir฀que฀programas฀ classificações),฀o฀programa2฀executava฀o฀seu฀bloco฀1,฀proces-
sem฀nenhuma฀relação฀possam฀se฀comunicar฀entre฀si.฀Os฀named฀ sando฀as฀suas฀rotinas฀de฀abertura฀e฀menu฀paralelamente฀ao฀
pipes฀também฀são฀usados฀para฀sincronizar฀processos,฀já฀que฀ programa1,฀ganhando฀dessa฀forma฀um฀bom฀tempo.฀O฀fragmento฀
em฀um฀determinado฀ponto฀você฀pode฀colocar฀um฀processo฀para฀ de฀código฀do฀programa2฀a฀seguir฀mostra฀a฀transição฀do฀seu฀
"ouvir"฀ou฀para฀"falar"฀em฀um฀determinado฀named฀pipe฀e฀ele฀daí฀ bloco฀1฀para฀o฀bloco฀2:
só฀sairá฀se฀outro฀processo฀"falar"฀ou฀"ouvir"฀aquele฀pipe.
Você฀já฀deve฀ter฀notado฀que฀essa฀ferramenta฀é฀ótima฀para฀ OK=`ca i e `
sincronizar฀processos฀e฀fazer฀bloqueio฀em฀arquivos฀de฀forma฀a฀ if [ $OK = a ]
evitar฀perda/corrupção฀de฀dados฀devido฀a฀atualizações฀simul- he
tâneas฀(a฀famosa฀concorrência).฀Vamos฀ver฀alguns฀exemplos฀ …
para฀ilustrar฀estes฀casos. R i a de i e ã

Tabela 1
Programa1 Programa2
Bloco 1 Rotina de classificação de três grandes arquivos Rotina de abertura e geração de menus
Bloco 2 Acertos finais e encerramento Impressão dos dados classificados pelo programa 1

agosto฀2005฀ edição฀11 87
[Link]
Linux฀User Papo฀de฀Botequim

… Então,฀o฀que฀fazer?฀Para฀resolver฀o฀problema฀de฀concor-
el e rência,฀vamos฀utilizar฀um฀named฀pipe.฀Criamos฀o฀script฀na฀
e i listagem 2฀que฀será฀o฀daemon฀que฀receberá฀todos฀os฀pedidos฀
fi para฀incrementar฀o฀contador.฀Note฀que฀ele฀vai฀ser฀usado฀por฀
qualquer฀página฀no฀nosso฀site฀que฀precise฀de฀um฀contador.฀
Após฀a฀execução฀de฀seu฀primeiro฀bloco,฀o฀programa2฀passará฀ Como฀apenas฀este฀script฀altera฀os฀arquivos,฀não฀existe฀o฀pro-
a฀"ouvir"฀o฀pipe1,฀ficando฀parado฀até฀que฀as฀classificações฀do฀ blema฀de฀concorrência.฀
Programa1฀terminem,฀testando฀a฀seguir฀a฀mensagem฀passada฀ Este฀script฀será฀um฀daemon,฀isto฀é,฀rodará฀em฀segundo฀plano.฀
pelo฀pipe1฀para฀decidir฀se฀os฀arquivos฀estão฀íntegros฀para฀serem฀ Quando฀uma฀página฀sofrer฀um฀acesso,฀ela฀escreverá฀a฀sua฀URL฀
impressos฀ou฀se฀o฀programa฀deverá฀ser฀descontinuado.฀Dessa฀ no฀pipe.฀Para฀testar,฀execute฀este฀comando:
forma฀é฀possível฀disparar฀programas฀de฀forma฀assíncrona฀e฀
sincronizá-los฀quando฀necessário,฀ganhando฀bastante฀tempo฀ ech e e agi a h l > i e c ad
de฀processamento.
Para฀evitar฀erros,฀em฀cada฀página฀a฀que฀quisermos฀adicionar฀
Bloqueio de arquivos o฀contador฀acrescentamos฀a฀seguinte฀linha:
Suponha฀que฀você฀tenha฀escrito฀um฀CGI฀(Common฀Gateway฀Inter-
face)฀em฀Shell฀Script฀para฀contar฀quantos฀hits฀uma฀determinada฀ <!-- e ec c d= ech $REQUEST URI > i e c ad -->
URL฀recebe฀e฀a฀rotina฀de฀contagem฀está฀da฀seguinte฀maneira:
Note฀que฀a฀variável฀$REQUEST URI฀contém฀o฀nome฀do฀arquivo฀
Hi = $ ca age hi > de ll || Hi = que฀o฀browser฀requisitou.฀Esse฀exemplo฀é฀fruto฀de฀uma฀troca฀
ech $ Hi =Hi > age hi de฀idéias฀com฀o฀amigo฀e฀mestre฀em฀Shell฀Thobias฀Salazar฀Tre-
visan,฀que฀escreveu฀o฀script฀e฀colocou-o฀em฀seu฀excelente฀site฀
Dessa฀forma,฀se฀a฀página฀receber฀dois฀ou฀mais฀acessos฀simul- ([Link]).฀Aconselho฀a฀todos฀os฀que฀querem฀aprender฀
tâneos,฀um฀ou฀mais฀poderá฀ser฀perdido,฀bastando฀que฀o฀segundo฀ Shell฀a฀dar฀uma฀passada฀lá.
acesso฀seja฀feito฀após฀a฀leitura฀do฀arquivo฀ age hi ฀e฀antes฀ Você฀pensa฀que฀o฀assunto฀named฀pipes฀está฀esgotado?฀Enga-
da฀sua฀gravação,฀isto฀é,฀após฀o฀primeiro฀acesso฀ter฀executado฀a฀ nou-se.฀Vou฀mostrar฀um฀uso฀diferente฀a฀partir฀de฀agora.
primeira฀linha฀do฀script฀e฀antes฀de฀executar฀a฀segunda.
Substituição de processos
Listagem 2: [Link] Vou฀mostrar฀que฀o฀Shell฀também฀usa฀os฀named฀
! bi ba h pipes฀de฀uma฀maneira฀bastante฀singular,฀que฀é฀a฀
substituição฀de฀processos฀(process฀substitution).฀Uma฀
PIPE= i e c ad a i a ed i e substituição฀de฀processos฀ocorre฀quando฀você฀põe฀
4 di de e a c l cad a i c ad e de cada agi a um฀ <฀ou฀um฀ >฀grudado฀na฀frente฀do฀parêntese฀da฀
5 DIR= a c ad esquerda.฀Digitar฀o฀comando:

[ - $PIPE ] || kfif $PIPE


$ ca < l -l
8
hile :
d Resultará฀no฀comando฀ l -l฀executado฀em฀um฀
f URL i $ ca < $PIPE sub-shell,฀como฀normal,฀porém฀redirecionará฀a฀saída฀
d para฀um฀named฀pipe฀temporário,฀que฀o฀Shell฀cria,฀
FILE= $DIR $ ech $URL | ed , * ,, nomeia฀e฀depois฀remove.฀Então฀o฀ca ฀terá฀um฀nome฀
4 a d da c dae c e e a i a li ha de฀arquivo฀válido฀para฀ler฀(que฀será฀este฀named฀pipe฀
5 ech a i = $FILE e฀cujo฀dispositivo฀lógico฀associado฀é฀ de fd ).฀
5
O฀resultado฀é฀a฀mesma฀saída฀que฀a฀gerada฀pelo฀฀
= $ ca $FILE > de ll || =
l -l,฀porém฀dando฀um฀ou฀mais฀passos฀que฀o฀usual.฀
8 ech $ = > $FILE
d e
Pra฀que฀simplificar?
d e ฀Como฀poderemos฀nos฀certificar฀disso?฀Fácil…฀Veja฀
o฀comando฀a฀seguir:

88 agosto฀2005฀ edição฀11
[Link]
Papo฀de฀Botequim Linux฀User

$ l -l > ca ! bi ba h
l- –– j e e j e e 4 A g : de fd -> i e:[ 5 ] LIST= C iada hell i ci al
l | hile ead FILE I ici d b hell
É…฀Realmente฀é฀um฀named฀pipe.฀Você฀deve฀estar฀pensando฀ d
que฀isto฀é฀uma฀maluquice฀de฀nerd,฀né?฀Então฀suponha฀que฀você฀ LIST= $FILE $LIST Al e ada de d b hell
tenha฀dois฀diretórios,฀chamados฀di ฀e฀di bk ,฀e฀deseja฀saber฀ d e Fi d b hell
se฀os฀dois฀são฀iguais.฀Basta฀comparar฀o฀conteúdo฀dos฀diretórios฀ ech $LIST
com฀o฀comando฀cmp:
฀ No฀início฀deste฀exemplo฀eu฀disse฀que฀ele฀era฀meramente฀
$ c < ca di * < ca di bk * || ech back f ad didático฀porque฀existem฀formas฀melhores฀de฀fazer฀a฀mesma฀
tarefa.฀Veja฀só฀estas฀duas:
ou,฀melhor฀ainda:
$ l | l
$c < ca di * < ca di bk * > de ll || ech back f ad
ou฀então,฀usando฀a฀própria฀substituição฀de฀processos:
Este฀é฀um฀exemplo฀meramente฀didático,฀mas฀são฀tantos฀os฀
comandos฀que฀produzem฀mais฀de฀uma฀linha฀de฀saída฀que฀ele฀ $ ca - < l
serve฀como฀guia฀para฀outros.฀Eu฀quero฀gerar฀uma฀listagem฀dos฀
meus฀arquivos,฀numerando-os,฀e฀ao฀final฀mostrar฀o฀total฀de฀ Um฀último฀exemplo:฀você฀deseja฀comparar฀a ฀e฀a ฀usando฀
arquivos฀no฀diretório฀corrente: o฀comando฀c ,฀mas฀esse฀comando฀necessita฀que฀os฀arquivos฀
estejam฀classificados.฀Então฀a฀melhor฀forma฀de฀proceder฀é:
hile ead a
d $ c < a < a
i a i a eh ece a i i iciali a i
ech $i: $a Essa฀forma฀evita฀que฀você฀faça฀as฀seguintes฀operações:
d e < < l
ech N di e i c e e ` d` e i e $i a i $ a >
$ a >
Tá฀legal,฀eu฀sei฀que฀existem฀outras฀formas฀de฀executar฀a฀ $ c
mesma฀tarefa.฀Usando฀o฀comando฀while,฀a฀forma฀mais฀comum฀ $ -f
de฀resolver฀esse฀problema฀seria:
Pessoal,฀o฀nosso฀papo฀de฀botequim฀chegou฀ao฀fim.฀Curti฀muito฀
l | hile ead a e฀recebi฀diversos฀elogios฀pelo฀trabalho฀desenvolvido฀ao฀longo฀
d de฀doze฀meses฀e,฀o฀melhor฀de฀tudo,฀fiz฀muitas฀amizades฀e฀tomei฀
i a i a eh ece a i i iciali a i muitos฀chopes฀de฀graça฀com฀os฀leitores฀que฀encontrei฀pelos฀
ech $i: $a congressos฀e฀palestras฀que฀ando฀fazendo฀pelo฀nosso฀querido฀
d e Brasil.฀Me฀despeço฀de฀todos฀mandando฀um฀grande฀abraço฀aos฀
ech N di e i c e e ` d` e i e $i a i barbudos฀e฀beijos฀às฀meninas฀e฀agradecendo฀os฀mais฀de฀100฀
emails฀que฀recebi,฀todos฀elogiosos฀e฀devidamente฀respondidos.฀
Ao฀executar฀o฀script,฀tudo฀parece฀estar฀bem,฀porém฀no฀coman- À฀saúde฀de฀todos฀nós:฀Tim,฀Tim.
do฀ ech ฀após฀o฀d e,฀você฀verá฀que฀o฀valor฀de฀$i฀foi฀perdido.฀ -฀Chico,฀fecha฀a฀minha฀conta฀porque฀vou฀pra฀casa!฀ ■
Isso฀deve-se฀ao฀fato฀desta฀variável฀estar฀sendo฀incrementada฀em฀
Julio Cezar Neves é Analista de Suporte de Sistemas desde 1969 e
Sobre฀o฀autor

um฀sub-shell฀criado฀pelo฀pipe฀(|)฀e฀que฀terminou฀no฀comando฀
d e,฀levando฀com฀ele฀todas฀as฀variáveis฀criadas฀no฀seu฀interior฀ trabalha com Unix desde 1980, quando participou do desenvolvi-
e฀as฀alterações฀lá฀feitas฀por฀variáveis฀criadas฀externamente. mento do SOX, um sistema operacional similar ao Unix produzido
Somente฀para฀te฀mostrar฀que฀uma฀variável฀criada฀fora฀do฀ pela Cobra Computadores. É autor do livro Programação Shell
Linux, publicado pela editora Brasport. Pode ser contatado no
sub-shell฀e฀alterada฀em฀seu฀interior฀perde฀as฀alterações฀feitas฀
e-mail [Link]@[Link]
quando฀o฀sub-shell฀se฀encerra,฀execute฀o฀script฀a฀seguir:

agosto฀2005฀ edição฀11 89
[Link]

Você também pode gostar