Você está na página 1de 5

���������������������������������������������������

����������������������������������������������������������������������������������������������������������������������������������������������������
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 - www.sxc.hu

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ê
$ logado jneves
jneves pts/0
12:02 (10.2.4.144)
jneves está logado
Oct 18 U
Ah, agora sim! Lembre-se dessa pega-
dinha: a maior parte dos comandos tem
uma 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
$ cat logado 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
#!/bin/bash então como ficaria: o comando test
# Pesquisa se um usuário está
# logado ou não $ cat logado Testes
#!/bin/bash Todos estamos acostumados a usar o
if who | grep $1 # Pesquisa se uma pessoa está if para testar condições, e estas são
then # logada ou não (versão 2) sempre maior que, menor que, maior
echo $1 está logado if who | grep $1 > /dev/null ou igual a, menor ou igual a, igual a e
else then
echo $1 não está no pedaço echo $1 está logado Tabela 1 – Opções do
fi else test para arquivos
echo $1 não está no pedaço 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! $ logado jneves -d arq arq existe e é um diretório
-r arq arq existe e com direito de leitura
– Aaah! Agora que já molhamos os nos- jneves está logado
-w arq arq existe e com direito de escrita
sos bicos, vamos dar uma olhada nos $ logado chico
-x arq arq existe e com direito de execução
resultados do seu programa: chico não está no pedaço

�����������������������������
84 edição 04 www.linuxmagazine.com.br
��������������������������������������������������������������������������������
����������������������������������������������������
�����������������������������������������������������������������������������������������������������������������������������������������������������
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 figura 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 test ! -d lmb não entendo nada de reino, fi lo, classe,
Shell Script usamos o comando test, só then ordem, família, gênero, espécie e outras
que ele é muito mais poderoso do que mkdir lmb 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 lmb 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- $ Familia=felinae
teste de cadeias de caracteres. tisse, e esta negativa deve-se ao ponto $ Genero=gato
de exclamação (!) precedendo a opção $ if test $Familia = canidea U
Tabela 3 – Opções do -d. Ao fi m da execução desse fragmento -a $Genero = lobo -o $Familia = U
test para números de script, com certeza o programa esta- felina -a $Genero = leão
ria dentro do diretório lmb. Vamos ver > then
Opção Verdadeiro se Significado
dois exemplos para entender a diferença > echo Cuidado
n1 -eq n2 n1 e n2 são iguais equal
na comparação entre números e entre > else
n1 -ne n2 n1 e n2 não são iguais not equal
cadeias de caracteres. > echo Pode passar a mão
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 cad1=1 Pode passar a mão
n1 -le n2 n1 é menor ou igual a n2 less or equal cad2=01
if test $cad1 = $cad2 Neste exemplo, caso o animal fosse
then da família canídea e (-a) do gênero lobo,
Pensa que acabou? Engano seu! Agora echo As variáveis são iguais. ou (-o) da familia felina e (-a) do gênero
é hora de algo mais familiar, as famosas else leão, seria dado um alerta, caso contrá-
comparações com valores numéricos. echo As variáveis são diferentes. 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 identifica que um comando con-
uns exemplos como isso tudo funciona. As variáveis são diferentes. 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 test -d lmb que a comparação seja numérica: Vamos mudar o exemplo para ver se o
then programa continua funcionando:
cd lmb cad1=1
else cad2=01 $ Familia=felino
mkdir lmb if test $cad1 -eq $cad2 $ Genero=gato
cd lmb then $ if test $Familia = felino -o U
fi echo As variáveis são iguais. $Familia = canideo -a $Genero = U
else onça -o $Genero = lobo
Tabela 4 echo As variáveis são diferentes. > then
fi > echo Cuidado
Operador Finalidade > else
Parênteses () 0
E vamos executá-lo novamente: > echo Pode passar a mão
> fi
Exclamação ! 0
As variáveis são iguais. Cuidado
-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

�����������������������������
www.linuxmagazine.com.br 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á ficar com a sintaxe semelhante à das
Artista1 e do Artista2, não é necessá- outras linguagens; por isso, esse será o
$Familia = canideo -a $Genero = U rio montar um if com o conector -o. O modo como o comando test será usado
onç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: $ egrep (Artista1|Artista2) U dade” na Tabela 5.
musicas
$Familia = felino -o FALSO -o U Tabela 5 - Tabela Verdade
$Genero = lobo Ou (nesse caso específico) 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
$grep Artista[12] musicas FALSO-VERDADEIRO FALSE TRUE
VERDADEIRO -o FALSO -o 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 test \($Familia = felino U do shell é muito mais poderoso que Ora, os caras que desenvolveram o
-o $Familia = canideo\) -a U os outros caretas - mas, cá entre nós, interpretador não são bobos e estão
\($Genero = onça -o $Genero = U essa construção de if test ... é muito sempre tentando otimizar ao máximo
lobo\) esquisita, é pouco legível. os algoritmos. Portanto, no caso do
> then – É, você tem razão, eu também não conector e, a segunda condição não será
> echo Cuidado gosto disso e acho que ninguém gosta. avaliada, caso a primeira seja falsa, já
> else Acho que foi por isso que o shell que o resultado será sempre falso. Já
> echo Pode passar a mão incorporou outra sintaxe, que substi- com o ou, a segunda será executada
> fi tui o comando test. somente caso a primeira seja falsa.
Pode passar a mão 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 test ! -d lmb exemplo de troca de diretório, que em
Para que seja VERDADEIRO o resul- then sua última versão estava assim:
tado de duas expressões ligadas pelo mkdir lmb
conector -a, é necessário que ambas fi if [ ! -d lmb ]
sejam verdadeiras, o que não é o caso cd lmb then
do exemplo acima. Assim, o resultado mkdir lmb
fi nal foi FALSO, sendo então o else cor- e utilizando a nova sintaxe, vamos fazê- fi
retamente executado. lo assim: cd lmb
Se quisermos escolher um CD que
tenha faixas de 2 artistas diferentes, nos if [ ! -d lmb ] O código acima também poderia ser
sentimos tentados a usar um if com o then escrito de maneira abreviada:
conector -a, mas é sempre bom lembrar mkdir lmb
que o bash nos oferece muitos recursos fi [ ! -d lmb ] && mkdir lmb
e isso poderia ser feito de forma muito cd lmb cd dir
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 ([]),
$ grep Artista1 musicas | grep U separados por espaços em branco dos [ -d lmb ] || mkdir lmb
Artista2 argumentos, o que aumentará enorme- cd dir

�����������������������������
86 edição 04 www.linuxmagazine.com.br
��������������������������������������������������������������������������������
����������������������������������������������������
�����������������������������������������������������������������������������������������������������������������������������������������������������
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 Significado
é 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 suficiente...
[...] Lista de caracteres modo correto: Vejamos um exemplo didático: depen-
| “ou” lógico dendo do valor da variável $opc o script
cd lmb || deverá executar uma das opções a
{ seguir: inclusão, exclusão, alteração ou
No primeiro caso, se o primeiro mkdir lmb encerrar sua execução. Veja como fica-
comando (o test, que está represen- cd lmb ria o código:
tado pelos colchetes) for bem sucedido, }
isto é, se o diretório lmb não existir, o if [ $opc -eq 1 ]
comando mkdir será executado porque Ainda não está legal porque, caso o then
a primeira condição era verdadeira e o diretório não exista, o cd exibirá uma inclusao
conector era e. mensagem de erro. Veja o modo certo: elif [ $opc -eq 2 ]
No exemplo seguinte, testamos se o then
diretório lmb existia (no anterior testa- cd lmb 2> /dev/null || exclusao
mos se ele não existia) e, caso isso fosse { elif [ $opc -eq 3 ]
verdade, o mkdir não seria executado mkdir lmb then
porque o conector era ou. Outra forma cd lmb alteracao
de escrever o programa: } elif [ $opc -eq 4 ]
then
cd lmb || mkdir lmb Como você viu, o comando if nos per- exit
mitiu fazer um cd seguro de diversas else
Nesse caso, se o comando cd fosse maneiras. É sempre bom lembrar que o echo Digite uma opção entre U
mal sucedido, o diretório lmb seria “seguro” a que me refi ro diz respeito ao 1 e 4
criado mas não seria feita a mudança de fato de que ao fi nal da execução você fi

�����������������������������
www.linuxmagazine.com.br edição 04 87
��������������������������������������������������������������������������������
���������������������������������������������������
����������������������������������������������������������������������������������������������������������������������������������������������������
LINUX USER Papo de Botequim

Quadro 1 - Script case $opc in O comando date informa a data com-


bem-educado 1) inclusao ;; pleta do sistema e tem diversas opções
2) exclusao ;; de mascaramento do resultado. Neste
#!/bin/bash
3) alteracao ;; comando, a formatação começa com
# Programa bem educado que
4) exit ;; um sinal de mais (+) e os caracteres de
# dá bom-dia, boa-tarde ou
*) echo Digite uma opção U formatação vêm após um sinal de per-
# boa-noite conforme a hora
entre 1 e 4 centagem (%), assim o %H significa a
Hora=$(date +%H)
esac hora do sistema. Dito isso, veja o exem-
case $Hora in
plo no Quadro 1.
0? | 1[01]) echo Bom 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:
1[2-7] ) echo Boa Tarde
é, se o asterisco atende a qualquer coisa,
;;
então servirá para qualquer coisa que 0? | 1 [01] – Zero seguido de qualquer
* ) echo Boa Noite
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"
esac
vírgula não é necessário antes do esac. com 01, 02, ... 09, 10 e 11;
exit
Vamos agora fazer um script mais 1 [2-7] – Significa 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 * – Significa 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 $ date – Cara, até agora eu falei muito e bebi
comando case, cuja sintaxe mostramos Tue Nov 9 19:37:30 BRST 2004 pouco. Agora eu vou te passar um
a seguir: $ date +%H exercício para você fazer em casa e
19 me dar a resposta da próxima vez em
case $var in que nos encontrarmos aqui no bote-
padrao1) cmd1 quim, tá legal?
cmd2 – Beleza!
cmdn ;; – É o seguinte: faça um programa que
padrao2) cmd1 receba como parâmetro o nome de
cmd2 um arquivo e que quando executado
cmdn ;; salve esse arquivo com o nome origi-
padraon) cmd1 nal seguido de um til (~) e abra esse
cmd2 arquivo dentro do vi para ser editado.
cmdn ;; Isso é para ter sempre uma cópia
esac 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 verificar 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 fluxo 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@gmail.com
com if ... elif ... else ... fi.

�����������������������������
88 edição 04 www.linuxmagazine.com.br
��������������������������������������������������������������������������������

Você também pode gostar