



Estude fácil! Tem muito documento disponível na Docsity
Ganhe pontos ajudando outros esrudantes ou compre um plano Premium
Prepare-se para as provas
Estude fácil! Tem muito documento disponível na Docsity
Prepare-se para as provas com trabalhos de outros alunos como você, aqui na Docsity
Encontra documentos específicos para os exames da tua universidade
Prepare-se com as videoaulas e exercícios resolvidos criados a partir da grade da sua Universidade
Responda perguntas de provas passadas e avalie sua preparação.
Ganhe pontos para baixar
Ganhe pontos ajudando outros esrudantes ou compre um plano Premium
Você não agüenta mais aquele seu amigo usuário de Linux enchendo o seu saco com aquela história de que o sistema é fantástico e o Shell é uma ferramenta maravilhosa? A partir desta edição vai ficar mais fácil entender o porquê deste entusiasmo... POR JULIO CEZAR NEVES
Tipologia: Notas de estudo
1 / 5
Esta página não é visível na pré-visualização
Não perca as partes importantes!




86 edição 06 www.linuxmagazine.com.br LINUX USER^ Papo de Botequim
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?
guagem! Eu fi z da forma que você pediu, olha só...
tomar um chope. Aê Chico, traz dois por favor. Um sem colarinho!
É muito fácil... $ cat contpal.sh #!/bin/bash
if [ $# -ne 1 ] then echo uso: $0 /caminho/do/U arquivo exit 2 fi Cont= for Palavra in $(cat $1) do Cont=$((Cont+1)) done echo O arquivo $1 tem $Cont U palavras. Ou seja, o programa começa, como sempre, verificando 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 padrão é branco, TAB e ENTER , que é exatamente o que desejamos para sepa- rar as palavras), incrementando a vari- ável $Cont. Vamos relembrar como é o arquivo ArqDoDOS.txt. $ cat ArqDoDOS.txt Este arquivo foi gerado pelo DOS/Rwin e foi baixado por um ftp mal feito. Agora vamos testar o programa pas- sando esse arquivo como parâmetro: $ contpal.sh ArqDoDOS.txt O arquivo ArqDoDOS.txt tem 14 palavras. Funcionou legal! Se você se lembra, em nossa última aula mostramos o loop for a seguir: for ((; i<=9;)) do let i++ echo -n "$i " done 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 forma $((expressão) ) ou let expressão. No último loop for usei a expansão aritmética das duas formas, mas não podemos seguir adiante sem saber que a expressão pode ser uma das listadas na tabela 1. Mas você pensa que o papo de loop (ou laço) se encerra no comando for? Ledo engano, amigo, vamos a partir de agora ver mais dois comandos. O comando while Todos os programadores conhecem este comando, porque é comum a todas as linguagens. Nelas, o que normalmente ocorre é que um bloco de comandos é executado, enquanto (enquanto, em inglês, é “while”) uma determinada condição for verdadeira. Dave Hamilton - www.sxc.hu Expressão Resultado id++ id-- pós-incremento e pós-decremento de variáveis ++id --id pré-incremento e pré-decremento de variáveis ** exponenciação * / % multiplicação, divisão, resto da divisão (módulo) + - adição, subtração <= >= < > comparação == != igualdade, desigualdade && E lógico || OU lógico Tabela 1: Expressões no Shell Blocos de código e laços (ou loops , como preferem alguns) 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 fim de refrescar o pensamento! POR JULIO CEZAR NEVES Curso de Shell Script
Botequim VI
��������������������������������������������������
���������������������������������������������������
��������������������������������������������������
���������������������������������������������������
Papo de Botequim LINUX USER ���������������������������������������������������������� ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������ www.linuxmagazine.com.br edição 06 87 Pois bem, isso é o que acontece nas linguagens caretas! Em programação Shell, o bloco de comandos é executado enquanto um comando for verdadeiro. E é claro, se quiser testar uma condi- ção, use o comando while junto com o comando test , exatamente como você aprendeu a fazer no if , lembra? Então a sintaxe do comando fica assim: while comando do cmd cmd ... cmdn done e dessa forma, o bloco formado pelas instruções cmd1, cmd2 ,... e cmdn é exe- cutado enquanto a execução da instru- ção comando for bem sucedida. Suponha a seguinte cena: tinha uma tremenda gata me esperando e eu estava preso no trabalho sem poder sair porque o meu chefe, que é um pé no saco (aliás chefe-chato é uma redun- dância, né?), ainda estava na sala dele, que fica bem na minha passagem para a rua. Ele começou a ficar cabreiro depois da quinta vez que passei pela sua porta e olhei para ver se já havia ido embora. Então voltei para a minha mesa e fi z, no servidor, um script assim: $ cat logaute.sh #!/bin/bash
while who | grep xefe do sleep 30 done echo O xato se mandou, não U hesite, dê exit e vá à luta Neste scriptzinho, o comando while testa o pipeline composto pelos coman- dos who e grep , que será verdadeiro enquanto o grep localizar a palavra xefe na saída do comando who. Desta forma, o script dormirá por 30 segundos enquanto o chefe estiver logado (Argh!). Assim que ele se desconectar do servi- dor, o fluxo do script sairá do loop e te mostrará a tão ansiada mensagem de liberdade. Mas quando executei o script, adivinha o que aconteceu? $ logaute.sh xefe pts/0 Jan 4 08:46 U (10.2.4.144) xefe pts/0 Jan 4 08:46 U (10.2.4.144) ... xefe pts/0 Jan 4 08:46 U (10.2.4.144) Isto é, a cada 30 segundos a saída do comando grep seria enviada para a tela, o que não é legal, já que poluiria a tela do meu micro e a mensagem tão espe- rada poderia passar despercebida. Para evitar isso, já sabemos que a saída do pipeline tem que ser redirecionada para o dispositivo /dev/null. $ cat logaute.sh #!/bin/bash
while who | grep xefe > /dev/null do sleep 30 done echo O xato se mandou, não U hesite, dê exit e vá a luta Agora quero montar um script que receba o nome (e eventuais parâme- tros) de um programa que será execu- tado em background e que me informe do seu término. Mas, para você enten- der este exemplo, primeiro tenho de mostrar uma nova variável do sistema. Veja estes comandos executados direta- mente no prompt: $ sleep 10& [1] 16317 $ echo $! 16317 [1]+ Done sleep 10 $ echo $! 16317 Isto é, criei um processo em back- ground que dorme por 10 segundos, somente para mostrar que a variável $! guarda o PID ( Process ID ) do último pro- cesso em background. Mas observe a listagem e repare, após a linha do Done , que a variável reteve o valor mesmo após o término desse processo. Bem, sabendo isso, já fica mais fácil monitorar qualquer processo em back- ground. Veja só como: $cat monbg.sh #!/bin/bash
$1 & # Coloca em backgroud while ps | grep -q $! do sleep 5 done echo Fim do Processo $ Esse script é bastante similar ao ante- rior, mas tem uns macetes a mais, veja só: ele tem que ser executado em back- ground para não prender o prompt mas o $! será o do programa passado como parâmetro, já que ele foi colocado em background após o monbg.sh propria- mente dito. Repare também na opção -q (quiet) do grep, que serve para fazê-lo “trabalhar em silêncio”. O mesmo resul- tado poderia ser obtido com a linha: while ps | grep $! > /dev/null , como nos exemplos que vimos até agora. Vamos melhorar o nosso velho musinc , nosso programa para incluir registros no arquivo musicas , mas antes preciso te ensinar a pegar um dado da tela, e já vou avisando: só vou dar uma pequena dica do comando read (que é quem pega o dado da tela), que seja o suficiente para resolver este nosso problema. Em uma outra rodada de chope vou te ensinar tudo sobre o assunto, inclusive como formatar tela, mas hoje estamos falando sobre loops. A sintaxe do comando read que nos interessa por hoje é a seguinte: $ read -p "prompt de leitura" var Onde “prompt de leitura” é o texto que você quer que apareça escrito na tela. Quando o operador teclar tal dado, ele será armazenado na variável var. Por exemplo: $ read -p "Título do Álbum: " Tit Bem, uma vez entendido isso, vamos à especificação do nosso problema: faremos um programa que inicialmente lerá o nome do álbum e em seguida fará um loop de leitura, pegando o nome da música e o artista. Esse loop termina quando for informada uma música com nome vazio, isto é, quando o operador
��������������������������������������������������
���������������������������������������������������
��������������������������������������������������
���������������������������������������������������
Papo de Botequim LINUX USER ���������������������������������������������������������� ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������ www.linuxmagazine.com.br edição 06 89 Em 20/01 às 11:23h Voltando à nossa CDteca, quando vamos cadastrar músicas seria ideal que pudéssemos cadastrar diversos CDs de uma vez só. Na última versão do programa isso não ocorre: a cada CD cadastrado o programa termina. Veja na listagem 2 como melhorá-lo. Nesta versão, um loop maior foi adi- cionado antes da leitura do título, que só terminará quando a variável $Para deixar de ser vazia. Caso o título do álbum não seja informado, a variá- vel $Para receberá um valor (coloquei 1, mas poderia ter colocado qualquer coisa) para sair desse loop, terminando o programa. No resto, o script é idêntico à versão anterior. Atalhos no loop Nem sempre um ciclo de programa, c o m p r e e n d i d o entre um do e um done , sai pela porta da frente. Em algu- mas oportunidades, temos que colocar um comando que aborte de forma c ont rolada esse loop. De maneira inversa, algumas vezes desejamos que o f lu xo de execução do programa volte antes de chegar ao done. Para isso, temos res- pectivamente os comandos break (que já vimos rapidamente nos exemplos do comando while ) e continue , que funcio- nam da forma mostrada na figura 1. O que eu não havia dito anterior- mente é que nas suas sintaxes genéricas eles aparecem da seguinte forma: break [qtd loop] e também: continue [qtd loop] Onde qtd loop representa a quanti- dade dos loops mais internos sobre os quais os comandos irão atuar. Seu valor por default é 1. Duvido que você nunca tenha apa- gado um arquivo e logo após deu um tabefe na testa se xingando porque não devia tê-lo removido. Pois é, na décima vez que fi z esta besteira, criei um script para simular uma lixeira, isto é, quando mando remover um (ou vários) arquivo(s), o programa “fi nge” que deletou, mas no duro o que ele fez foi mandá-lo(s) para o diretório /tmp/ LoginName_do_usuario. Chamei esse programa de erreeme e no arquivo /etc/ profile coloquei a seguinte linha, que cria um “apelido” para ele: alias rm=erreeme Veja o programa na listagem 3. Como você pode ver, a maior parte do script é formada por pequenas críticas aos parâmetros informados, mas como o script pode ter recebido diversos arqui- vos a remover, a cada arquivo que não se encaixa dentro do especificado há $ cat musinc.sh #!/bin/bash
Para= until [ "$Para" ] do clear read -p "Título do Álbum: " Tit if [! "$Tit" ] # Se titulo vazio... then Para=1 # Liguei fl ag de saída else if grep "^$Tit^" musicas > /dev/null then echo "Este álbum já está cadastrado" exit 1 fi Reg="$Tit^" Cont= oArt= while [ "$Tit" ] do echo Dados da trilha $Cont: read -p "Música: " Mus [ "$Mus" ] || break # Sai se vazio read -p "Artista: $oArt // " Art [ "$Art" ] && oArt="$Art" # Se vazio Art anterior Reg="$Reg$oArt~$Mus:" # Montando registro Cont=$((Cont + 1))
done echo "$Reg" >> musicas sort musicas -o musicas fi done Listagem 2 Figura 1: A estrutura dos comandos break e continue , usados para contro- lar o fluxo de execução em loops. �� �������� �������� ���� ��������������� ����� ��������������� �������� ����� ����� �� �������� �������� ���� ����� ��������
������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������
��������������������������������������������������
��������������������������������������������������
90 edição 06 www.linuxmagazine.com.br LINUX USER^ Papo de Botequim um continue , para que a seqüência volte para o loop do for de forma a receber outros arquivos. Quando você está no Windows (com perdão da má palavra) e tenta remover aquele monte de lixo com nomes esqui- sitos como HD04TG.TMP, se der erro em um dos arquivos os outros não são removidos, não é? Então, o continue foi usado para evitar que uma improprie- dade dessas ocorra, isto é, mesmo que dê erro na remoção de um arquivo, o programa continuará removendo os outros que foram passados.
estar curioso para ver o programa que restaura o arquivo removido, não é? Pois então aí vai vai um desafio: faça-o em casa e me traga para dis- cutirmos no nosso próximo encontro aqui no boteco.
çar, pois não sei nem como começar...
o que se faz em Shell: extrema- mente fácil. É para ser feito em, no máximo, 10 linhas. Não se esqueça de que o arquivo está salvo em /tmp/ $LOGNAME e que sua última linha é o diretório em que ele residia antes de ser “removido”. Também não se esqueça de criticar se foi passado o nome do arquivo a ser removido.
é mole! Qualquer dúvida é só passar um email para julio.neves@gmail. com. Agora chega de papo que eu já estou de goela seca de tanto falar. Me acompanha no próximo chope ou já vai sair correndo para fazer o script que passei?
ele pensa! $ cat erreeme.sh #!/bin/bash
if [ $# -eq 0 ] then echo "Erro -> Uso: erreeme arq [arq] ... [arq]" echo "O uso de metacaracteres e’ permitido. Ex.U erreeme arq*" exit 1 fi
MeuDir="/tmp/$LOGNAME"
if [! -d $MeuDir ] then mkdir $MeuDir # Vou criá-lo fi
if [! -w $MeuDir ] then echo "Impossivel salvar arquivos em $MeuDir. U Mude as permissões..." exit 2 fi
Erro=
for Arq do
if [! -f $Arq ] then echo "$Arq nao existe." Erro= continue # Volta para o comando for fi
DirOrig=dirname $Arq
if [! -w $DirOrig ] then echo "Sem permissão no diretorio de $Arq" Erro= continue # Volta para o comando for fi
if [ "$DirOrig" = "$MeuDir" ] then echo "$Arq fi cara sem copia de seguranca" rm -i $Arq # Pergunta antes de remover
[ -f $Arq ] || echo "$Arquivo removido" continue fi
para usá-lo em um script de undelete cd $DirOrig pwd >> $Arq mv $Arq $MeuDir # Salvo e removo echo "$Arq removido" done
exit $Erro Listagem 3: erreeme.sh Julio Cezar Neves é Analista de Suporte de Sistemas desde 1969 e tra- balha com Unix desde 1980, quando participou do desenvolvimento do SOX, um sistema operacional similar ao Unix produzido pela Cobra Com- putadores. Pode ser contatado no SOBRE O AUTOR e-mail [email protected]