7/21/2019 Manual de Programao Shell (2)
1/59
PROGRAMAOBOURNE-SHELL
Fernando Fernndez - MoreData
ABERTURA
Para alm da utilizao no dia-a-dia, o Shell pode ser usado para criar programas que se transformam em
novos comandos. Estes programas so designados geralmente "shell scripts" ou "shell procedures". Este
manual pretende ensinar a forma de criar e executar estes programas, utilizando comandos, variveis,
parmetros posicionais, cdigos de resultado e estruturas de controlo de fluxo bsicas.
A programao em Shell muito til para criar pequenos programas que realizam tarefas do dia-a-dia,
que poderiam ser realizadas mo utilizando os comandos j existentes no UNIX.
Quer o Bourne-Shell quer o C-Shell so apropriados para realizar programao, mas o Bourne-Shell
executa mais rpidamente os programas e o C-Shell no existe em todas as mquinas UNIX. Por isto
http://www.moredata.pt/~ferdezhttp://www.moredata.pt/7/21/2019 Manual de Programao Shell (2)
2/59
optamos e aconcelhamos a que toda a programao shell seja feita em Bourne-Shell, de modo a que os
programas sejam mais port'aveis e mais rpidos. Todo este manual foi realizado com esta ideia em mente.
PROGRAMAO EM SHELL
1. SHELL SCRIPTS
1.1 Criao de um pequeno shell script
Vamos comear por criar um pequeno script que efectue as seguintes tarefas:
- Mostrar o nome do directrio corrente.
- Listar o contedo do directrio corrente.
- Indicar que terminou a tarefa.
Estas tarefas poderiam ser executadas manualmente atravs da utilizao dos comandos "pwd", "ls" e
"echo". Para automatizar esta tarefa basta criar um ficheiro com os comandos dentro. Utilize o seu editor
preferido para criar um ficheiro chamado "dl" (directory list) com o seguinte contedo:
$ cat dl
pwd
ls
echo "fim do script"
$
Figura 1. Visualizao do script dl
Se j acabou, j tem o seu primeiro programa escrito em shell! Para o executar basta, a partir do shell,
digitar o seguinte comando:
7/21/2019 Manual de Programao Shell (2)
3/59
sh dl
Figura 2. Execuo de um shell script
Os comandos contidos no ficheiro "dl" so executados sequncialmente pelo shell: o nome do directrio
mostrado primeiro, seguido do resultado do comando ls, e finalmente o echo diz "fim do script.".
Se dl um comando til, possivel transform-lo num ficheiro executvel, utilizando o comando chmod:
$ ls -l dl-rw------- 1 Manel ic 29 Jan 4 14:49 dl
$ chmod u+x dl
$ ls -l dl
-rwx------ 1 Manel ic 29 Jan 4 14:49 dl
$ dl
/usr/users/ic/fernandez/tx
SU2
dl
fim do script.
Figura 3. dl como um ficheiro executvel
1.2. Criao de um directrio 'BIN' para conter os scripts
O passo seguinte tornar os nossos novos comandos acessveis a partir de ualquer directrio, tal como os
comandos comuns do UNIX, que esto localizados nos directrios /bin e /usr/bin. Comeamos por
arrum-los cuidadosamente num sub-directrio bin do nosso directrio.
Seguidamente alteramos a varivel de ambiente PATH de modo a que o shell passe a procurar comandos
tambm neste nosso sub-directrio.
$ cd
$ mkdir bin
7/21/2019 Manual de Programao Shell (2)
4/59
$ mv dl bin/dl
$ ls -l bin
total 1
-rwx------ 1 Manel ic 29 Jan 4 14:49 dl
$ echo $PATH
/bin:/usr/bin
$ echo $HOME
/usr/users/ic/fernandez
$ PATH=$HOME/bin:$PATH
$ echo $PATH
/usr/users/ic/fernandez:/bin:/usr/bin
$
Figura 4.Preparao do ambiente de trabalho
Agora, se tudo correu bem, ser possivel chamar o novo comando "dl" de qualquer directrio.
Experimente.
O nome "bin" dado ao nosso sub-directrio no obrigatrio. Podiamos ter-lhe chamado "progs" ou
"scripts" ou at "xkyzz.dir", mas optmos por escolher um nome antigo da tradio UNIX - "bin" - que
usado para directrios que contm programas executveis. Mas se optar por mudar o nome ao seu no se
esquea de alterar tambm a varivel PATH.
1.3. Avisos acerca dos nomes dos shell scripts
possivel dar qualquer nome ao script, desde que este seja um nome de ficheiro v'alido. No entanto, no
nada aconcelhvel [1] dar-lhes nomes de comandos j existentes no sistema. Por exemplo, se
tivssemos chamado "mv" ao nosso programa, cada vez que tent'assemos mudar o nome a um ficheiro o
shell executaria este nosso script. Dificilmente seria o que desejvamos...
Outro problema surgiria se lhe cham'assemos "ls", j que o prprio script invoca o comando ls. Seria
criado um ciclo infinito, j que cada chamada ao nosso programa "ls" invocaria outro comando "ls" e
nunca terminaria nenhum deles. Aps algum tempo, o sistema emitiria a seguinte mensagem de erro: "Too
many processes, cannot fork" que significa que foram criados demasiados processos, atingindo o limite
7/21/2019 Manual de Programao Shell (2)
5/59
imposto pelo sistema.
O que aconteceu? Digitmos o nosso novo comando - ls. O shell leu o ficheiro e executou o primeiro
comando - pwd. Ento leu o segundo comando - ls - e tentou executar outra vez o nosso comando ls. Isto
criou um ciclo infinito, porque cada um dos comandos "ls" executa outro comando "ls" e s pra quandoum deles no consegue chamar o seguinte, porque o sistema j no deixa.
Os criadores do UNIX, sbiamente, limitaram o nmero de vezes que um ciclo infinito deste gnero
executa. Uma forma de evitar que isto acontea, mantendo o nome "ls" do nosso comando indicar o
nome completo do comando "ls" do sistema no script:
$ cat bin/ls
pwd
/bin/ls
echo "fim do script."
$
Figura 5. Comando 'ls' alterado
A partir de Ento, a nica forma de executar o verdadeiro comando "ls" seria invocando-o com o seu
nome completo: "/bin/ls".
2. VARIVEIS
As variveis so os objectos bsicos manipulados pelos programas de shell. O outro tipo de objectos so
os ficheiros. Vamos discutir aqui trs tipos de variveis e como podem ser usados:
- Parmetros posisionais.
- Parmetros especiais.
- Variveis identificadas (ou simplesmente: variveis).
7/21/2019 Manual de Programao Shell (2)
6/59
2.1. Parmentos posicionais
Um parmetro posicional uma varivel dentro de um shell script cujo valor fornecido pelo utilizador
que chama o programa com argumentos na linha de comando. Cada argumento corresponde a um
parmetro posicional e estes esto numerados pela ordem com que foram colocados na linha de comando.
Os parmetros posicionais so referidos utilizando um sinal "$" seguido do nmero de ordem: $1, $2, $3, e
assim por diante.
Um programa em shell pode referenciar at nove parmetros posicionais. Se um programa em shell fr
chamado do seguinte modo:
$ myprog um dois trs quatro cinco seis sete oito nove
Ento o parmetro $1, dentro do programa ter o valor "um", o parmetro $2 ter o valor "dois", e assim
por diante.
Vamos criar um script chamado pp (no nosso directrio bin) para verificar o funcionamento dos
parmetros posicionais. Este programa vai conter comandos echo de forma a mostrar cada um dos
argumentos com que o programa fr chamado.
$ cat bin/pp
echo O primeiro argumento : $1echo O segundo argumento : $2
echo O terceiro argumento : $3
echo O quarto argumento : $4
$
Figura 6. Script que mostra os argumentos
No nos podemos esquecer de utilizar o comando "chmod u+x bin/pp". Seguidamente podemos ento
experimentar o seu funcionamento:
7/21/2019 Manual de Programao Shell (2)
7/59
$ pp abc 94902 XPTO 2j%#j9-88
O primeiro argumento : abc
O segundo argumento : 94902
O terceiro argumento : XPTO
O quarto argumento : 2j%#j9-88
$
Figura 7.Utilizao dos parmetros posicionais
Com o programa que se segue possivel enviar via "mail" uma mensagem de aniversrio para outro
utilizador [2]da mquina.
$ cat bin/parabensbanner Parabens! | mail $1
$ parabens suzana
$
Figura 8.Exemplo til de script com argumentos
A Suzana, quando entrar no sistema, recebe uma agradvel mensagem de parabns enviada por ns.
O comando "who" lista informao de quem est a trabalhar no sistema na altura em que executado.
Como criar um pequeno comando chamado "quem" que informe se determinado utilizador est a trabalhar
correntemente?
Crie o seguinte ficheiro:
$ cat bin/quem
who | grep $1
$
Figura 9.Programa 'QUEM'
O comando "who" lista todos os utilizadores, e o "grep" procura uma linha contendo o que vier no
primeiro argumento.
7/21/2019 Manual de Programao Shell (2)
8/59
Tente utilizar o seu nome (o "logname", evidentemente, j que o sistema no conhece outro) como
argumento do novo comando "quem". Digamos, por exemplo, que o seu logname "ana". Quando se digita
o comando "quem ana", o programa substituir $1 por "ana" e executar o comando "who | grep ana".
$ quem ana
ana tty18 Jan 5 11:38
$
Figura 10.Utilizao do comando 'quem'
Este novo comando pode ainda ser utilizado para descobrir se algum est a trabalhar em determinado
terminal. Imaginemos que queramos saber se o terminal "tty18" estava ocupado.
$ quem tty18
manel tty18 Jan 5 11:38
$
Figura 11.Outra utilizao do script 'quem'
J que o grep encontrou uma linha com "tty18" isto significaria que este posto de trabalho estava ocupado
de momento.
Embora o shell permita chamar programas com um mximo de 128 argumentos, os scripts esto
restringidos a um mximo de nove parmetros posicionais, de $1 a $9. esta restrio pode ser torneada
atravs da utilizao do comando "shift", que funciona do seguinte modo:
$ cat bin/shift.ex
echo O primeiro argumento : $1
echo O segundo argumento : $2
echo O terceiro argumento : $3
echo O quarto argumento : $4
echo " n n n"
shiftecho "Shiftou... n"
echo Agora o primeiro argumento : $1
echo Agora o segundo argumento : $2
7/21/2019 Manual de Programao Shell (2)
9/59
echo Agora o terceiro argumento : $3
echo Agora o quarto argumento : $4
$
Figura 12.Comando 'shift'
A execuo do script "shift.ex" d o seguinte output:
$ shift.ex AAA BBB CCC DDD EEE FFF
O primeiro argumento : AAA
O segundo argumento : BBB
O terceiro argumento : CCC
O quarto argumento : DDD
Shiftou...
Agora o primeiro argumento : BBB
Agora o segundo argumento : CCC
Agora o terceiro argumento : DDD
Agora o quarto argumento : EEE
Figura 13.Resultado do script 'shift.ex'
O parmetro especial "$*", descrito na seco seguinte, tambm pode ser usado para acesso aos valores
de todos os argumentos que vm da linha de comando.
2.2. Parmetros especiais
2.2.1. Nmero de Argumentos - $#
Este parmetro, quando referido num programa de shell, contm o nmero de argumentos com que o
programa foi invocado. O seu valor pode ser utilizado em qualquer lugar do programa.
$ cat bin/get.num
echo O nmero de argumentos $#
$ get.num a b c d
O nmero de argumentos 4
$
Figura 14.Parmetro especial $#
2.2.2 Todos argumentos - $*
7/21/2019 Manual de Programao Shell (2)
10/59
Este parmetro contm uma string com todos os argumentos com que o programa foi invocado. No est
restringido aos nove parmetros posicionais, $1 a $9.
possivel criar um pequeno script que demonstre a utilizao deste parmetro:
$ cat bin/show.paramecho $*
$ show.param Isto so os parmetros deste script.
Isto so os parmetros deste script.
$
Figura 15.Parmetro especial $*
Existe tambm outro parmetro especial - $@ - com um significado semelhante mas que tem ligeiras
diferenas que no discutiremos aqui.
2.2.3. Estado de sada do ltimo comando - $?
Este parmetro contm o estado de sada do ltimo comando executado dentro do programa. Como o leitor
deve saber, no UNIX os programas terminam devolvendo um valor numrico entre 0 e 255. Se o programa
correu sem problemas deve devolver 0 se encontrou alguma situao esquisita que no tenha podidocontrolar devolve outro valor qualquer, normalmente 1. Mais para diante neste curso falaremos de como
fazer com que os nossos prprios scripts devolvam "exit status" para quem os chamou. Neste momento
vamos apenas ver como consultar o "exit status" de um programa que tenhamos chamado. O exemplo que
se segue no um programa mas uma sesso de shell interactiva, o que ajuda a demonstrar que o que se
faz em scripts tambm se pode fazer mo, e vice-versa.
$ cat myfile
this is the contents of this file.
$ echo $?
0
$ cat xpto
cat: cannot open xpto
$ echo $?2
$
7/21/2019 Manual de Programao Shell (2)
11/59
Figura 16.Exit status - Parmetro $?
2.2.4. Nmero do processo - $$
Outra coisa que o leitor deve saber que cada pedido de execuo de um programa numa mquina UNIX
d origem criao de um processo. No vamos aqui debater a natureza dos processos, mas
fundamental que o leitor saiba que todos os processos so numerados e que se dois utilizadores pedirem
simultneamente a execuo do mesmo programa, sero criados dois processo diferentes (embora
parecidos).
possivel, em shell [3]saber qual o nmero do processo que corresponde ao nosso programa atravs da
consulta do parmetro $$ como se exemplifica seguidamente:
$ ps
PID TTY TIME COMMAND
4195 tty18 0:04 sh
$ echo $$
4195
$
Figura 17.Nmero do nosso processo - parmetro $$
2.2.5. Nmero de processos em background - $!
O parmetro $! contm o nmero de processo do ltimo comando invocado para background. Eis um
exemplo:
$ sleep 500 &
4490
$ ps
PID TTY TIME COMMAND
4195 tty18 0:04 sh
4490 tty18 0:04 sleep
$ echo $!
4490
$ kill -9 $!
4490 Killed
7/21/2019 Manual de Programao Shell (2)
12/59
$
Figura 18.Parmetro $!
2.3 Variveis identificadas
Este um nome muito esquisito para se dar quilo que se designa sempre por "variveis", e dificilmente o
ireis encontrar no resto deste texto. Os nomes das variveis so da responsabilidade do
programador/utilizador (isto , da nossa responsabilidade). Os valores delas tambm so da nossa
responsabilidade. Para quem j programou noutras linguagens, isto no se afigurar muito estranho. As
variveis do shell so normalmente designadas "strings" nas outras linguagens de programao.
No exemplo seguinte, var1 uma varivel e abcdef789 o valor que nela se vai colocar:
var1=abcdef789
Um "$" colocado antes do nome da varivel indica ao shell que deve substituir a sequncia $var1 pelo seu
contedo: "abcdef789". O primeiro caracter de um nome de varivel deve ser uma letra ou um underscore
("_"). O resto do nome da varivel pode ser constituido por letras, underscores ou algarismos. Tal como
nos nomes dos programas, no aconcelhvel utilizar nomes de comandos nos nomes das variveis. Alm
disto, o shell tem alguns nomes de variveis reservados para si. Uma breve explanao destas pode ler-se
seguidamente:
CDPATH: define o caminho de pesquisa para o comando "cd".
HOME: o directrio para onde se desloca o comando "cd" se
invocado sem argumentos.
IFS: contm os separadores de campos (argumentos) para a
avaliao dos argumentos de um comando (isto tem muito
que se lhe diga!...).
LOGNAME: o nome do utilizador.
MAIL: o ficheiro que contm o correio electrnico.PATH: o caminho de pesquisa de comandos (j falmos dele antes).
PS1: a string de pedido de comando (em sesses interactivas),
7/21/2019 Manual de Programao Shell (2)
13/59
normalmente "$ ".
PS2: a string secundria de pedido de comando (em sesses
interactivas), normalmente "> ".
TERM: o tipo de terminal, para ser usado pelos programas que usam
as bases de dados de terminais (TERMCAP e TERMINFO).
2.4. Afecto de variveis
Podem-se afectar os valores contidos pelas variveis de vrios modos:
- Utilizar o modo "var=contedo".
- Utilizar o comando "read var" para que o prprio shell pe,ca o valor para a varivel.
- Redireccionar o output de um comando para dentro de uma varivel utilizando os acentos graves
("`...`").
- Assignar um parmetro posicional a uma varivel.
As seces que se seguem discutem detalhadamente cada um destes mtodos.
2.4.1 Utilizao do sinal '=' (afectao)
Qualquer varivel pode ser afectada com o sinal "=" com qualquer valor. Este valor sempre considerado
como uma string de caracteres e no deve conter espaos, a menos que seja indicada entre pelicas ou
aspas. Assim sendo, dizer
a=Joao
ou
a="Joao Alberto Costa Morais"
ou ainda
x=123
so utilizaes vlidas do operando "=" enquanto que
b=Joao Alberto Costa Morais
7/21/2019 Manual de Programao Shell (2)
14/59
est errado.
2.4.2 Utilizao do comando 'Read'
O comando "read" inserido num script shell indica ao shell que deve pedir o valor da varivel e afect-la.
assim possivel fazer entradas de dados interactivas com programas de shell. O formato geral para a
utilizao deste comando :
read varivel
Se um programa utilizar o comando "echo" antes de invocar o "read" possivel dar indicaes ao
utilizador do gnero de "Indique o nome ...", de forma a que este saiba o que lhe est a ser pedido. O
comando read esperar at que o utilizador digite uma string terminada por , e a varivel
passa a conter esta string. Todas as subsequentes invocaes de $varivel sero substituidas pela string
que o utilizador digitou.
O exemplo seguinte mostra como criar um programa que permite consultar uma agenda telefnica contida
num ficheiro chamado "tellist". O nosso programa chamar-se- "telefone".
$ cat bin/telefone
echo "Indique o nome a procurar ou parte deste: c"
read nome
grep nome tellist
$ telefone
Indique o nome a procurar ou parte deste: PedroPedro Ferreira 253 88 56
$
Figura 19.Programa 'telefone'
Crie um ficheiro chamado "tellist" com alguns nomes como o seguinte:
$ cat tellist
Pedro Ferreira 253 88 56
Palma 87 26 88
7/21/2019 Manual de Programao Shell (2)
15/59
Ana Ferreira 253 38 91
Rui Martins 77 63 21
$
Figura 20.Ficheiro 'tellist' com a lista telefnica.
A sequncia " c" evita que o comando "echo" termine a mensagem mudando de linha.
O exemplo que se segue um programa chamado "faz_lista" que adiciona nomes lista telefnica
existente:
$ cat bin/faz_lista
echo "Nome: c"
read nomeecho "Telefone: c"
read telefone
echo $nome $telefone >> tellist
echo "Registo adicionado."
$ faz_lista
Nome: Alberto Albertini
Telefone: 829949182
Registo adicionado.
$
Figura 21.Programa de adio lista telefnica.
O programa funciona da seguinte forma:
echo envia uma mensagem para o terminal pedindo o nome de uma
pessoa.
read l do teclado (standard input) o nome da pessoa e afecta a
varivel "nome" com esse valor.
echo envia nova mensagem a pedir o nmero telefnico da pessoa.
read l o nmero.
echo com o output redireccionado, cria novo registo no ficheiro
que contm a lista telefnica.
echo envia ao utilizador uma mensagem final, que indica que oprograma terminou.
7/21/2019 Manual de Programao Shell (2)
16/59
O leitor deve lembrar-se que se quizer que o output do comando "echo" seja adicionado ao fim do ficheiro
da lista telefnica deve usar ">>". Se usasse apenas ">" o ficheiro conteria apenas o ultimo nmero de
telefone que tivesse sido adicionado.
de notar tambm que a varivel "nome" vai ser afectada, no s pelo primeironome "Alberto" mas portoda a resposta do utilizador, at ao fim da linha - "Alberto Albertini".
2.4.3. Afectao de uma varivel com o output de um comando
sempre possvel referir o output de qualquer comando em shell atravs da notao
`comando`
Portanto, a maneira bvia de afectar uma varivel com o output de um comando
var=`comando`
O contedo da varivel modificado para conter o output do comando. Experimente o seguinte programa,
que lhe dar a hora do dia, com base na data do sistema (que dada pelo comando "date", como j sabe).
$ cat bin/h
time=`date | cut -c12-19`
echo "So $time"
$ h
So 14:41
$
Figura 22.Script para saber as horas.
fundamental no deixar espaos de cada lado do sinal "=". Se se deixar um espao do lado esquerdo o
shell tentar executar um hipottico comando com o nome da varivel. Se se deixar um espao direita
do sinal, este espao vai fazer parte do valor com que se est a afectar a varivel.
2.4.4 Afectao com parmetros posicionais
7/21/2019 Manual de Programao Shell (2)
17/59
possivel afectar uma varivel com um parmetro posicional utilizando o seguinte formato:
var=$1
3. PASSO EM FRENTE
A programao em shell tem algumas particularidades que a tornam flexivel:
- Comentrios, que permitem documentar a funo dos programas.
- Redireccionamento interno, que permite ter dentro do texto do programa o standard input de um
comando.
- O comando "exit", que permite abortar um programa em qualquer ponto da sua execuo
devolvendo "exit status" a quem os chamou.
- Os comandos para programao de tarefas cclicas [4]- "for" e "while".
- Os comandos condicionais - "if" e "case" - que permitem executar comandos apenas se
determinadas condies existirem.
- O comando "break", que permite sair incondicionalmente de um loop.
3.1 Comentrios
possivel manter comentrios num programa atravs da utilizao do caracter "#". Todo o texto existente
numa linha Aps o "#" ignorado. O "#" pode estar colocado no incio da linha, caso em que toda a linha
ignorada, mas tambm pode estar colocado aps um comando, caso em que o comando executado,
mas o resto da linha ignorado.
Por exemplo, o programa que contm as seguintes linhas ignora-las- quando fr executado:
# Este programa envia parabns# Este programa recebe como argumento um logname, que
# espera que seja vlido.
7/21/2019 Manual de Programao Shell (2)
18/59
Figura 23.Comentrios inseridos num programa.
3.2 Redireccionamento interno
O redireccionamento interno permite ao programador colocar no script .linhas que vo servir de input a
um comando. uma forma de providenciar input a um comando sem ter que recorrer a outro ficheiro
adicional. A notao consiste no smbolo "
7/21/2019 Manual de Programao Shell (2)
19/59
Maria:
Soube que fazes anos. Parabns.
Manel
? q
$
Figura 25.Recepao dos parabns.
3.3 Utilizao do 'ED' dentro de um script
O redireccionamento interno fornece um meio til e conveniente para usaro editor "ed" num script. Se oleitor no est familiarizado com este editor no precisa de se preocupar. O seu funcionamento
extremamente simples e ser-lhe- muito fcil compreender o exemplo. Imagine que quer criar um
programa que altere um texto contido num ficheiro. Manualmente, isso faria isso entrando no seu editor
preferido e executando um comando de substituio global (desde que exista nesse editor). Vamos
apresentar aqui um exemplo de como isso pode
ser automatizado, usando o editor "ed" e o redireccionamento interno. Veja-se o script que se segue:
$ cat bin/subst
# ENTRADA DE DADOS
echo "Ficheiro a alterar: c"
read file
echo "Texto a substituir: c"
read oldtext
echo "Texto a colocar: c"
read newtext
# SUBSTITUIO DO TEXTO
ed - $file g/$oldtext/s//$newtext/g
wq
!
$
7/21/2019 Manual de Programao Shell (2)
20/59
Figura 26.Comando 'subst'
Repare-se na opo "-" do "ed" que faz com que este programa trabalhe silenciosamente, no enviando
mensagens para o terminal. Note-se tambm a forma do comando do "ed" para efectuar a substituio
global:
g/texto_velho/s//novo_texto/g
O programa usa trs variveis: file - que vai conter o nome do ficheiro a modificar - oldtext - o texto que
vai ser mudado - e newtext - o texto a colocar. Quando o programa corre, utilizado o comando read para
obter os valores destas variveis.
Uma vez entrados os valores nas variveis o redireccionamento interno redirecciona a substituio global
do texto, a escrita e o comando de sada, para dentro do input do "ed".
$ cat tellist
Pedro Ferreira 253 88 56Palma 87 26 88
Rui Martins 77 63 21
Ana Ferreira 253 38 91
Alberto Albertini 82873 10923
$ subst
Ficheiro a alterar: tellist
Texto a substituir: Palma
Texto a colocar: F. Palma$ cat tellist
Pedro Ferreira 253 88 56
F. Palma 87 26 88
Rui Martins 77 63 21
Ana Ferreira 253 38 91
Alberto Albertini 82873 10923
$
Figura 27.Utilizao do comando 'subst'
7/21/2019 Manual de Programao Shell (2)
21/59
3.4.Estados de saida - Exit Status
A maior parte dos comandos devolvem estados de sada para indicar como correu a sua execuo. Por
conveno, se devolverem 0 (zero) a execuo foi bem sucedida, se devolverem outro valor significa que
aconteceu algo de extraordinrio que o programa no pde resolver. O cdigo devolvido no mostrado
automticamente mas est disponivel no parmetro $?.
J vimos mais atrs como se pode verificar o contedo desta varivel, mas vamos agora como fazer com
que os nossos scripts possam devolver tambm valores a quem os chamou.
Um script termina normalmente quando o ltimo comando nele contido acaba de ser executado. No
entanto, possivel abortar um script em qualquer altura (a partir de dentro, e no com a tecla
do terminal) atravs do comando "exit". Mais importante ainda, pode-se invocar o comando exit com um
argumento numrico que vai ser o estado de sada do programa.
exit 0
ou
exit 1
Figura 28.Exemplos de invocao do exit.
3.5. Ciclos
Nas seces anteriores deste curso os comandos dos scripts foram sempre executados de uma forma
linear. Os primeiros comandos do ficheiro so executados primeiro e os seguintes depois. Comeamos
aqui o estudo das estruturas de controlo que permitiro alterar esta forma
de funcionamento, alterando a sequncia de execuo dos comandos, de uma forma perfeitamente
controlada.
Os comandos "for" e "while" de execuo ciclica, permitem que um programa execute um comando ou
uma sequncia de comandos repetidas vezes.
7/21/2019 Manual de Programao Shell (2)
22/59
3.5.1. O ciclo 'For'
O ciclo "for" executa uma sequncia de comandos uma vez por cada membro de uma lista. Tem o
seguinte formato:
for varivel in lista_de_valores
do
comando_1
comando_2
comando_3
.
.
.
ultimo_comando
done
Figura 29.Formato do ciclo 'for'
Em cada iterao do ciclo, a varivel afectada com um dos membros da lista. Dentro do corpo do ciclo
(isto , entre o "do" e o "done"), podem ser feitas referncias varivel para consultar o seu contedo.
mais fcil ler um programa se as construces ciclicas estiverem visualmente claras. J que o shell
ignora os espaos a mais, cada seco de comandos pode ser indentada tal como se viu na figura anterior.
Para alm disto, torna-se mais simples verificar se cada "do" tem um "done" correspondente.
A varivel escolha do programador. Por exemplo, se lhe chamamos "var", os valores dados na lista
aps a palavra "in" sero colocados na varivel "var" um de cada vez, e os comandos entre o "do" e o
"done" executados uma vez para cada um dos valores. Qualquer referncia ao valor "$var" ser
substituida pelo valor do momento. Se a clausula "in ..." fr omitida, a varivel ser afectada com a lista
de argumentos do programa - "$*".
Quando os comandos entre o "do" e o "done" tiverem sido executados para o ltimo elemento lista ser
executada a linha seguinte do "done", continuando assim a execuo normal do programa. Se no existir
7/21/2019 Manual de Programao Shell (2)
23/59
nenhuma linha aps o "done" o programa terminar normalmente.
A forma mais simples de compreender isto tudo atravs de um exemplo. Vamos criar um programa que
mova os ficheiros de um directrio um por um para outro directrio, indicando prviamente a operao.
Os seguintes comandos so usados:
echo para pedir o directrio.
read para ler o nome do directrio do telclado.
for varivel para obrigar o programa a entrar em ciclo, com a varivel
como varivel de controlo.
in lista para indicar a lista de valores que vo ser colocados na
varivel, um por cada ciclo.
do comandos para indicar os comandos a executar ciclicamente.
A figura seguinte mostra o texto do script mvall
$ cat bin/mvall
echo "Qual o directrio destino dos ficheiros? c"
read pathname
for file in *
do
echo "Mudan,ca do ficheiro $file: em curso... c"
sleep 2
mv $file $pathname
echo " rMudan,ca do ficheiro $file: efectuada. "done
$
Figura 30.Script mvall.
Entre o "do" e o "done" existe uma particularidade a referir. O leitor pode estar neste momento a
perguntar-se para que servir a sequncia " r" no segundo "echo", e para que ser que este existe. Se
tentar executar este script verificar que lhe enviada a primeira mensagem, que passados alguns
7/21/2019 Manual de Programao Shell (2)
24/59
segundos "mgicamente" substituida pela segunda. Isto devido sequncia " c" " r", que permite
voltar a escrever na mesma linha. Como j vimos, a sequncia " c" evita que o cursor mude de linha aps
um "echo". A sequncia " r" desloca o cursor para o incio da linha em que este est no momento. Assim,
o cursor, que aps o primeiro "echo" est colocado no fim da mensagem "...em curso..." reposto no
inicio dessa linha pelo segundo "echo" e a mensagem que este envia sobrepe-se que j existia no ecr.
3.5.2 O ciclo 'While'
Outra instruco de execuo cclica o "while", que usa dois grupos de comandos. O segundo grupo
ser executado ciclicamente enquanto o ltimo comando do primeiro grupo fr executado devolvendo "exit
status" 0 (zero), significando que foi bem sucedido.
O formato genrico do "while" o seguinte:
while
comando_1
comando_2
comando_3
.
.
.
ltimo_comando
do
comando_1
comando_2 comando_3
.
.
.
ltimo_comando
done
Figura 31.Ciclo 'while' - Formato genrico
O leitor deve estar lembrado do script que permitia introduzir dados na lista telefnica, que se chamava
7/21/2019 Manual de Programao Shell (2)
25/59
"fazlista". Vamos agora desenvolver uma nova verso deste script, que permitir introduzir vrios nomes
e nmeros de telefone com uma invocao apenas.
$ cat bin/faz_lista2
echo "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
echo "Introduo de dados para lista telefnica - Verso
II"
echo "\n"
while
echo "Nome (^d para terminar):\c"
read nome
do
echo "Telefone:\c"
read telefone
echo $nome $telefone >> tellist
echo "Registo adicionado."
done
echo "\n"
echo "Lista criada ou alterada."
$
Figura 32.Script 'faz_lista2'
3.5.3 O ciclo 'Until'
Este ciclo muito semelhante ao ciclo "while" sendo apenas diferente na forma de execuo. O segundo
grupo de comandos ser executado at que o primeiro grupo seja bem sucedido o que exatamente ao
contrrio do "while". No vamos demorar-nos muito sobre este ciclo devido sua extraordinria
semelhana com o "while". O seu formato o que se segue:
until
comando_1
comando_2
comando_3
7/21/2019 Manual de Programao Shell (2)
26/59
.
.
.
ltimo_comando
do
comando_1 comando_2
comando_3
.
.
.
ltimo_comando
done
Figura 33.Ciclo until - Formato genrico
3.6 O caixote do lixo: '/dev/null'
A rvore de directrios de quase todas as mquinas UNIX contm um ficheiros especial onde se pode
depositar todo o output indesejado. Por exemplo: um programa em shell, tinha que garantir que um ficheiro
no existia, e portanto deveria remov-lo se existisse. Como fazer isso? A forma mais rpida seria:
rm file 2> /dev/null
As mensagens de erro do comando "rm" seriam redireccionadas para o caixote do lixo do sistema - o
ficheiro especial /dev/null. Se o ficheiro "file" existisse o "rm" remov-lo-ia silenciosamente, caso
contrrio emitiria uma mensagem de erro que no seria mostrada.
3.7 Execuo Condicional
3.7.1. If...THEN...FI
O comando "if" funciona de forma muito semelhante ao ciclo "while", mas o teste ao resultado do
primeiro grupo de comandos s se efectua uma nica vez. O formato genrico do comando "if" o
seguinte:
7/21/2019 Manual de Programao Shell (2)
27/59
if
comando_1
comando_2
comando_3
.
.
.
ltimo_comando
then
comando_1
comando_2
comando_3 .
.
.
ltimo_comando
fi
Figura 34.'if...then...fi' - Formato genrico
Eis um exemplo da utilizao do comando "if":
$ cat bin/tem
echo "Escreva o nome do ficheiro e a palavra a pesquisar:"
read file word
if grep $word $file > /dev/null
then
echo "A palavra $word existe no ficheiro $file."
fi
$
Figura 35.Um grep diferente - tem
So de notar duas coisas neste script. Uma que a leitura das duas variveis feita num nico "read", o
que serve para relembrar uma forma menos habitual de o usar. A outra o redireccionamento do grep,
que evita que seja mostrado o output deste comando sempre que a palavra exista no ficheiro. No se deve
7/21/2019 Manual de Programao Shell (2)
28/59
pensar que ao escrever
if grep $word $file > /dev/null
estamos a redireccionar o "if". Isso seria um grave erro. Tudo o que vem entre a palavra "if" e a palavra
"then" um grupo de comandos, e como tal, redireccionveis.
3.7.2. If...THEN...ELSE...FI
Vimos que a seguir ao "then" so escritos os comandos que devem ser executados se o primeiro grupo,
que est entre o "if" e o "then" fr bem sucedido e se quizessemos executar comandos caso este grupo
no fosse bem sucedido? Os construtores do Shell tambm
pensaram nisto e providenciaram uma extenso ao "if ... then ... fi", o "else" que significa "seno". O
formato genrico o que se segue:
if
comando_1
comando_2
comando_3
.
.
.
ltimo_comando
then
comando_1
comando_2
comando_3
.
.
.
ltimo_comando
else
comando_1
comando_2
comando_3
.
.
7/21/2019 Manual de Programao Shell (2)
29/59
.
ltimo_comando
fi
Figura 36.' if...then...else...fi' - Formato genrico
possivel alterar ligeiramente o programa "tem" de forma a torn-lo um pouco mais simptico, de forma
a indicar no s a existncia da palavra no ficheiro mas tambm a sua no-existncia:
$ cat bin/tem
echo "Escreva o nome do ficheiro e a palavra a pesquisar:"
read file word
if grep $word $file > /dev/null
then
echo "A palavra $word existe no ficheiro $file."
else
echo "A palavra $word NO existe no ficheiro $file."
fi
$
Figura 37.Um grep diferente - 'tem' - verso II
3.7.3. CASE...ESAC
A construcoo "case ... esac" permite testar o contedo de uma varivel e reagir de diferentes formas,
consoante o seu valor. Enquanto o "if" se poderia traduzir para
se ISTO ento AQUILO seno AQUELOUTRO
o "case" poder-se- traduzir
caso VARIVEL seja
____ X executar comando 1
____ Y executar comando 2
____ Z executar comando 3
Figura 38.Como funciona um 'case'
7/21/2019 Manual de Programao Shell (2)
30/59
Em Shell, o "case" tem a seguinte forma:
case $varivel in
caso1)
comando_1
comando_2
.
.
ltimo_comando
caso2)
.
. .
esac
Figura 39.case - formato genrico
A grande vantagem do "case" que possivel colocar metacaracteres nas strings de comparao, que
esto representadas na figura por "caso1" e "caso2" vamos ver uma aplicao disto.
Imaginemos que um dos nossos scripts, tal como j aconteceu, recebe informao atravs dos seus
argumentos, que tm que ser dois. Podemos usar para este exemplo o script "tem" que realizmos h
algumas seces atrs. Vamos alter-lo para que receba o nome do ficheiro e a palavra por argumentos,
em vez de perguntar com o "echo" e o "read".
$ cat bin/tem2
# tem - verso II - pesquisa palavras em ficheiros
file=$1
word=$2
if grep $word $file > /dev/null
then
echo "A palavra $word existe no ficheiro $file."else
echo "A palavra $word NO existe no ficheiro $file."
fi
7/21/2019 Manual de Programao Shell (2)
31/59
$
Figura 40.script 'tem' - verso usando argumentos
O que acontecer se o utilizador se esquecer de dar argumentos ao programa? "Culpa dele!", dir o
programador mais descontraido. No uma atitude muito simptica e a melhor forma de actuar ser
alterar o programa de forma a que este saiba reagir elegantemente aos erros do
utilizador. Neste caso vamos alterar o programa, utilizando o parmetro $# para testar a existncia de
argumentos e o seu nmero. Vamos colocar no incio as seguintes linhas:
case $# in
0) echo "$0: necessrios argumentos"
exit 1
1) echo "falta palavra para procurar no ficheiro '$1'"
exit 1
2)
*) # todos os outros casos...
echo "$0: demasiados argumentos" exit 1
esac
Figura 41.teste aos argumentos.
Vejamos o que acontece: usado um "case" para testar o conteudo do parmetro $#, que contm o
nmero de argumentos com que o programa foi invocado. Se o utilizador no der argumentos $# conter 0,e ser enviada para o terminal a mensagem que diz que o programa precisa de ser invocado com
argumentos. O parmetro "$0" um parmetro posicional que contm o nome do programa, a primeira
palavra do comando digitado no shell. Se o utilizador s der um argumento o programa assume que o
utilizador se esqueceu de indicar a palavra e avisa. Caso o utilizador fornea dois argumentos o no se
faz nada nesta fase, deixando todas as aces efectuarem-se normalmente, mais tarde. No caso de
existirem mais de dois
argumentos o programa emite tambm uma mensagem de erro e aborta. Este caso um exemplo da
possibilidade de utilizar metacaracteres no "case", e a utilizao do asteristico significa "todos os outros
casos".
7/21/2019 Manual de Programao Shell (2)
32/59
Em qualquer dos casos o programa funciona graciosamente e ajuda o utilizador a corrigir os seus prprios
erros. Isto simptico, e pode poupar muito trabalho ao programador, que no ser tantas vezes
incomodado por causa de um "comportamento esquisito" do seu programa, quando o que se trata apenas
de uma utilizao incorrecta.
3.8 'TEST': Um comando til
O comando "test" verifica se certas condies so verdadeiras e devolve um "exit tatus" correspondente.
Serve fundamentalmente para ser usado em ciclos "while" testes "if", que veremos mais adiante. Como o
leitor j sabe, o ciclo "while" esta o "exit status" do comando e executa ciclos enquanto este fr zero, queignifica execuo bem sucedida.
possivel usar o comando "test" para verificar vrios tipos de condies, como se ver seguidamente.
tambm importante focar que o comando "test" tem duas formas. A forma mais convencional
test argumentos
mas existe tambm outra forma, destinada a tornar os programas mais legveis pelos programadores
habituados s outras linguagens de programao, que
[ argumentos ]
Esta segunda forma de longe a mais usada, e ns no iremos fugir a esta regra, mas convm no nos
esquecermos de que "test" um comando, e que "[" apenas outra forma de o invocar.
Quando usado na forma "[" o comando "test" exige um "]" no fim da linha de comando.
Vamos agora ver qual o potencial deste comando e como o usar.
7/21/2019 Manual de Programao Shell (2)
33/59
7/21/2019 Manual de Programao Shell (2)
34/59
um caracter).
[ -f file ] Verdadeiro se "file" existe e ficheiro regular.
[ -d file ] Verdadeiro se "file" existe e directrio.
[ -b file ] Verdadeiro se "file" existe e ficheiro especial de
blocos.
[ -c file ] Verdadeiro se "file" existe e ficheiro especial de
caracteres.
[ -u file ] Verdadeiro se "file" existe e tem o SUID BIT ligado.
[ -g file ] Verdadeiro se "file" existe e tem o SGID BIT ligado.
[ -k file ] Verdadeiro se "file" existe e tem o STICKY BIT ligado.
3.8.2. Igualdade de strings
Tambm possivel usar o comando "test" para verificar a igualdade de variveis permitindo assim testar
automticamente o seu contedo de uma forma mais simples do que com a utilizao do comando "case".
Apesar disto o "case" devemos lembrar que o "case" bastante mais potente e que embora o "test" seja
usado para a maior parte das comparaes de variveis aquele mantm o seu enorme potencial.
O uso do "test" para comparaes de strings simples. O teste seguinte
[ $var1 = $var2 ]
ser verdadeiro se os contedos forem idnticos.
O exemplo que se segue o caso tipico de um programa que executa ciclicamente at que o utilizador
digite a opo de terminar.
resposta="s"
until [ "$resposta" = n ]
do
7/21/2019 Manual de Programao Shell (2)
35/59
.
.
.
ac,c~ao a realizar
.
. .
echo "quer continuar (s/n) ? c"
read resposta
done
Figura 43test - exemplo de comparaoo de strings
Uma pergunta pode surgir: porque est a varivel "resposta" entre aspas durante o teste?
Isto pode no parecer bvio mas imaginemos que o primeiro ciclo se efectuava e o utilizador respondia
com um . A varivel ficava vazia. Ao realizar o teste o programa invocaria
[ = n ]
que uma forma errada de usar o comando "test". Colocar aspas na varivel evita este inconveniente.
completamente diferente, e perfeitamente aceit'avel para o "test" ser chamado assim:
[ "" = n ]
Sempre que uma varivel possa ter um contedo nulo os testes devem ser feitos colocando a varivel
entre aspas. Se se tiver d'uvidas usem-se as aspas.
3.8.3. Comparao numrica
O comando "test" permite tambm a comparaoo numrica de variveis. Como o leitor sabe, as variveis
do shell s tm um tipo: string [5]. Como tal podem conter todo o tipo de caracteres, desde a letras
maiusculas e minusculas, algarismos (na informtica chamados digitos) ou quaisquer outros caracteres do
7/21/2019 Manual de Programao Shell (2)
36/59
cdigo ASCII. At agora no vimos nenhuma forma de realizar operaes aritmticas em programas shell
(e ainda no aqui, mas mais frente...) mas, j que as variveis podem conter digitos porque no
comparar os valores descritos por esses digitos?
o que faz o "test", da seguinte forma:
[ $var1 -eq $var2 ] Verdadeiro se os valores forem (numericamente) iguais.
[ $var1 -ne $var2 ] Verdadeiro se os valores forem diferentes.
[ $var1 -gt $var2 ] Verdadeiro se o valor $var1 fr maior do que o valor $var2.
[ $var1 -ge $var2 ] Verdadeiro se o valor $var1 fr maior ou igual do que o
valor $var2.
[ $var1 -lt $var2 ] Verdadeiro se o valor $var1 fr menor do que o valor $var2.
[ $var1 -le $var2 ] Verdadeiro se o valor $var1 fr menor ou igual do que o
valor $var2.
3.8.4. Expresses lgicas
Para os programadores mais exigentes, o "test" permite adicionar condies lgicas s expresses. Pode-
se compr diversas expresses com AND's (conjunes) OR's (disjuno) e NOT's (negao). Pode-se
at utilizar parntesis, que tm, no entanto que ser colocados entre aspas ou com uma barra (\) para que o
shell no lhes d significado especial.
-a conjuno (and).
-b disjuno (or).
! negao (not).
Se por exemplo, quizessemos saber se um ficheiro tem permisses de leitura mas no de execuo
fariamos:
7/21/2019 Manual de Programao Shell (2)
37/59
if [ -r $file -a "(" -x $file ")" ]
then
.
.
.
Figura 44.test - condies
3.9. Controlo incondicional: 'BREAK' e 'CONTINUE'
O comando "break" pra incondicionalmente a execuo de qualquer ramo dentro do qual seja encontrado,
e prossegue a Execuo na instruco seguinte ao "done", "fi" ou "esac". Se no existirem instruces
aps este o programa termina.
O comando "continue" faz com que o programa reinicie imediatamente um novo ciclo, ignorando o que
resta dos comandos entre o "do" e o "done".
O exemplo que se segue um excerto de um programa que tem de processar o contedo de um ficheiro,
saltando linhas de comentrio (que, tal como no Shell, so comeadas por "#") e terminando o
processamento, no no fim do ficheiro, mas quando encontrar a palavra "fim" isolada numa linha.
.
.
.
.while read linha
do
case $linha in
"#"*)
continue
fim)
break
7/21/2019 Manual de Programao Shell (2)
38/59
esac
# AQUI PROCESSA A LINHA
.
.
.
done < /tmp/datafile$$
.
.
.
Figura 45.break e continue - exemplo de utilizao
3.10. Aritmtica EXPR
O comando "expr" ptimo para realizar operaes aritmticas em scripts de Shell. Como j repararam,
dentro das variveis do Shell pode-se ter qualquer conjunto de caracteres, inclusiv
algarismos. Ento porque no realizar operaes com os seus contedos? O Shell no providencia
nenhum operador numrico mas existe um utilitrio que permite avaliar expresses numricas. Este
comando o "expr", e normalmente utilizado do seguinte modo:
resultado=`expr $opr1 + $opr2`
ou
resultado=`expr $val / 3`
ou ainda
resultado=`expr $val + $opr1 $opr2 `
O leitor pode estranhar a utilizao das barras na expresso lembre-se que os parantesis e o asteristico
tm significado especial para o Shell - so metacaracteres e que esse significado tem que ser "desligado"
com a barra invertida ('\').
O "expr", infelizmente, no efectua operaes com casas decimais, pelo que sempre que isto sejanecessrio ser'a preciso recorrer ao "bc", utilizado provvelmente com redireccionamento interno.
7/21/2019 Manual de Programao Shell (2)
39/59
4. TCNICAS MAIS AVANADAS
4.1. Resoluo de problemas
Os scripts de Shell nem sempre funcionam primeira, e nos casos em que o script grande dificil
encontrar o(s) ponto(s) do texto onde existem erros. Os maiores problemas no so os erros de sintaxe, j
que o shell indica-os atravs do nmero de linha. O mais dificil de corrigir so os erros de lgica, em que
o programa executa mas no faz o que queremos.
Para ajudar nestas situaes, os programadores que fizeram o Shell, que sabem bem o que custam estas
situaes, criaram um mecanismo que permite visualizar a execuo do programa.
Para activar este mecanismo, que permite visualizar cada comando do script antes de ser executado, basta
inserir
set -x
no texto do programa. Para desactivar este mecanismo deve-se usar "+x" em vez de "-x". Veja-se o
exemplo.
.
.
.
# aqui comea a rea do programa que parece no funcionar bemset -x
.
.
.
# e aqui termina
set +x
# resto do programa...
.
.
.
7/21/2019 Manual de Programao Shell (2)
40/59
Figura 46.deteco de erros lgicos
4.2. O comando 'SET'
J conhecemos vrias utilidades do comando "set". Comemos por us-lo para visualizar variveis e o
seu contedo, vimos ainda agora que permite ligar e desligar o mecanismo de deteco de erros lgicos e
vamos agora observar ainda outra utilidade: permitir alterar os valores contidos nos parmetros
posicionais $1, $2, $3, etc., e nos parmetros especiais $* e $#. Como que isso se faz?
$ cat bin/setex
# mostra parmetros com que foi invocado
echo $*
echo numero de argumentos $#
set `ls`
echo $*
echo agora numero de argumentos $#
Figura 47.alterao dos argumentos
4.3. Leitura ficheiros cim o 'WHILE READ'
Imaginemos agora que temos um ficheiro com dados num determinado formato e que queremos processar
as linhas desse ficheiro uma a uma. Isto talvez seja um conceito novo para o leitor que no est habituado
a programar, e portanto vamos tentar enquadrar este exemplo numa situao real.
Admitamos que existe uma instalao UNIX onde o administrador de sistema imps aos utilizadores a
existencia de um ficheiro com nomes de outros ficheiros ou directrios dos quais preciso fazer backups
regularmente. Se um utilizador quer fazer backups dos seus dados basta criar um ficheiro chamado
"backup.lst" no seu directrio pessoal. Quando o administrador fr realizar os backups limitar-se- a ler
os nomes dos ficheiros a arquivar dos diversos "backup.lst" de cada um dos utilizadores (provavelmente
usar o comando find para os encontrar) e criar uma lista geral.
7/21/2019 Manual de Programao Shell (2)
41/59
$ cat backup.lst
/usr/acct/rosa/c.progs
/usr/acct/rosa/textos
/usr/acct/rosa/i4gl/progs
/usr/acct/rosa/bin/l
/usr/acct/rosa/bin/p
/usr/acct/rosa/bin/s
/usr/acct/rosa/.profile
$
Figura 48.exemplo de um ficheiro backup.lst
Como procederia o administrador de sistema para realizar os backups? Eis uma hiptese:
$ find / -name backup.lst -print > /tmp/lista1
$ cat `cat /tmp/lista1` > /tmp/lista2
$ tar cvF /tmp/lista2
Figura 49.exemplo de backups realizados mo
O administrador de sistema que realiza os backups do modo que acima se indicou limita-se a cumprir os
seus deveres sem grande entusiasmo. No se preocupa, por exemplo com ficheiros mal preenchidos. Um
utilizador pode ter um nome de directrio mal escrito no seu backup.lst, no o saber e julgar que os seus
dados esto a ser convenientemente salavaguardados, e enquanto isso o "tar" no consegue ler o ficheiro.
Como resolver isto?
No necessrio aumentar o trabalho do administrador. Basta automatizar de forma conveniente esta
tarefa atravs de um bom script. Eis outra hiptese:
$ cat /usr/local/bin/userbackup
# userbackup verso I - backup de ficheiros pedidos pelos utilizadores
# ficheiros temporrios
ERROS=/tmp/tf1$$
LISTA=/tmp/tf2$$
CORREIO=/tmp/tf3$$
true > $LISTA
# fase 1: criar lista de ficheiros e directrios
find / -name backup.lst -print | while read listfiledo
# mensagem
echo "encontrado ficheiro $listfile. processando..."
#inicializar o ficheiro de erros e a varivel indicadora
true > $ERROS
7/21/2019 Manual de Programao Shell (2)
42/59
# descobrir o dono do ficheiro atravs do comando ls e do
# comando set o ls devolve este formato:
#
# 2 -rw-r--r-- 1 Manel iC 26 abr 11 11:31 backup.lst
set `ls -sl $listfile`
dono=$4
# validar todos os nomes contidos no ficheiro do utilizador
echo "validao dos dados em $listfile..."
while read filename
do # se o nome corresponde a um ficheiro regular ou directrio
if [ -f $filename -o -d $filename ]
then
# verificar se o ficheiro tem dados
if [ -s $filename ]
then
echo $filename >> $LISTA
else
echo "*** AVISO: $filename est vazio." >> $ERROS
fi
else
echo "*** ERRO: $filename no bom." >> $ERROS
fi
done < $listfile
(continua na pgina seguinte)
if [ -s $ERROS ]
then
echo "encontrados erros_. correio para o dono: $dono"
echo "\\n\\n\\nERRO S no backup de `date`\\n\\n" > $CORREIO
cat $ERROS >> $CORREIO
mail $dono < $CORREIO
fi
done
# fase 2: arquivo
echo "criao do arquivo..."
tar cvFf $LISTA /tmp/tar
# fase 3: remoo dos temporrios
rm $ERROS $LISTA $CORREIO 2> /dev/null
echo "fim do backup."
$
Figura 50.userbackup: script de backupsEis um programa onde a confuso pode aumentar devido ao seu tamanho.
altura de usar o comando "set -x" quando no funciona. Mas no caso para sustos. Mais adiante
vamos estudar a maneira de simplificar a programao de tarefas assim...
Como curiosidade, vejamos o correio que chegou a um utilizador descuidado, que tinha o seu "backup.lst"
mal preenchido:
7/21/2019 Manual de Programao Shell (2)
43/59
From root Wed Apr 11 12:52 LIS 1990
Relatrio do backup de quarta-feira 11 de abril 1990
12:52:51
*** AVISO: /tmp/jk est vazio - ignorado.
*** ERRO: /tmp/jkl no regular nem directrio.
? d
$
Figura 51.mensagem de aviso
4.4. A varivel 'IFS'
A varivel IFS, j abordada anteriormente indica ao shell quais os caracteres que separam os diversos
campos de um registo de entrada. Um registo de entrada pode ser uma linha de comando, ou uma linha
que tenha que ser avaliada pelo comando "read".
Vejamos o primeiro caso: o que separa as vrias palavras (campos) que constituem o comando e os seus
argumentos? Normalmente espaos, mas de um modo geral so brancos isto , espaos, tabs e newlines,
em nmero indeterminado.
No segundo caso, se por exemplo invocarmos
read a b c d
o que que influencia o que ser colocado em cada uma das variveis? Mais uma vez os caracteres
brancos
No entanto, este comportamento pode ser alterado se alterarmos a varivel IFS. Dentro desta varivel
esto os caracteres que podem ser reconhecidos como separadores de campos na entrada (Input Field
Separators). Esta varivel de ambiente, que por defeito contm trs caracteres (espao, tab e newline),
pode ser modificada do seguinte modo:
IFS=":,+=%"
7/21/2019 Manual de Programao Shell (2)
44/59
caso em que os novos separadores de campo passariam a ser os caracteres ":,+=%". Uma experincia
interessante experimentar o seguinte:
IFS=":"
e verificar que se podem emitir os comandos com o sinal ":" a separar as palavras em vez de espaos,
como a seguir se exemplifica.
$ IFS=":"
$ export IFS$ ls:-l:/tmp
total 666
-rw-r--r-- 1 ccat iC 0 abr 10 16:19 3
-rw------- 1 Manel iC 68608 abr 11 15:24 Ex03394
-rw------- 1 Manel iC 5120 abr 11 15:22 Rx03394
-rw-r--r-- 1 root root 0 abr 10 17:20 TPERROR
drwxr-xr-x 2 root root 32 abr 9 12:34 WORK
-rw-r--r-- 1 Manel iC 190 abr 11 15:17 jk
-rw-r--r-- 1 Manel iC 37 abr 11 11:32 lista1
-rw-r--r-- 1 Manel iC 26 abr 11 11:33 lista2
-rw-rw-r-- 1 root sys 272 abr 9 10:24 sa.adrfl
-rw-r--r-- 1 Manel iC 0 abr 11 12:48 tf23071
-rw-r--r-- 1 Manel iC 49152 abr 11 14:25 toprn.3272
-rw-r--r-- 1 Manel iC 8 abr 9 14:26 xx
-rw-r--r-- 1 Manel iC 3 abr 9 14:31 xy
$
Figura 52.alterao de varivel IFS
No fica muito legvel pois no? No entanto, a alterao da varivel IFS pode ter bastante utilidade.
Vejamos o caso de um script que quer ler o ficheiro /etc/passwd.
.
.
7/21/2019 Manual de Programao Shell (2)
45/59
.
IFS=":"
while read nome password id gid comment dir shell
do
# cautela repe-se o IFS com espao, tab e newline
IFS="
"
# processa cada linha
.
.
.
done < /etc/passwd
IFS="
"
Figura 53.leitura de dados de um ficheiro
4.5. Execuo condicional sem 'IF'
Existem em Shell outros metecaracteres pouco utilizados, que so muito teis para evitar utilizao
grande escala dos if. Estes metacaracteres so os metacaracteres de execuo condicional: "&&" e "||".
possvel executar um comando se e s se o anterior fr bem sucedido utilizando o metacaracter "&&",
da seguinte forma:
comando1 && comando2
Tambm possivel executar um comando see s se o comando anterior fr bem sucedido: forma:
comando1 || comando2
Assim, se quisermos testar a existncia de um programa antes de o executar poderemos usar o mtodo
que a seguir se descreve:
7/21/2019 Manual de Programao Shell (2)
46/59
7/21/2019 Manual de Programao Shell (2)
47/59
significado semelhante ao anterior (com algumas diferenas
que no discutiremos aqui) e recebido quando o utilizador
carrega em CTRL- .
TERMINATE(15): a utilizao simples do comando "kill" d'a origem ao envio
deste sinal, que significa que o programa deve serimediatamente interrompido o "shutdown" envia este sinal a
todos os processos existentes na mquina momentos antes de
enviar o sinal que se segue.
KILL(9): este sinal pode ser enviado atravs da utilizao do comando
"kill -9 ..." e implica a interrupo imediata do processo a
que est destinado.
NOME: NM T DESCRIO
SIGHUP 1 A HANGUP (Terminal desligado ou linha
cortada).
SIGINT 2 M INTERRUPT (Utilizador carregou em
Delete, Rubout ou Ctrl-C).
SIGQUIT 3 M QUIT (Utilizador carregou em Ctrl-\).
SIGKILL 9 M KILL (Algum matou o processo).
SIGBUS 10 A BUS ERROR (Erro interno ao programa).
SIGSEGV 11 A SEGMENTATION VIOLATION (Programa
mal comportado).
SIGPIPE 13 A BROKEN PIPE (Pipe sem sada)
SIGTERM 15 Software Termination Signal From Kill.
SIGUR1 16 M User Defined Signal 1.
SIGUR2 17 M User Defined Signal 2.SIGCLD 18 A Death Of A Child.
SIGPWR 19 A Power-Fail Restart.
7/21/2019 Manual de Programao Shell (2)
48/59
Figura 54. Sinais mais usados.
A resposta recepo de sinais varia conforme a sua importncia e nalguns casos pode ser alterada,
como veremos mais adiante. Normalmente, quando um processo recebe um SIGUP, SIGINT, SIGQUIT,
SIGTERM ou SIGKILL, a sua execuo imediatamente interrompida. Por outro lado, se receber umSIGPWR, SIGCLD ou SIGPIPE, SIGUSR1 ou SIGUSR2 a sua
execuo proseguir normalmente. Esta reaco pode ser alterada para qualquer sinal, excepto o
SIGKILL, que provoca sempre a morte do processo.
Na programao Shell (nas outras os mtodos variam grandemente) os sinais podem ser "apanhados", isto
, podemos modificar a atitude do programa em relao recepo de sinais, atravs da utilizao do
comando "trap".
a) podemos igorar sinais que de outra forma causariam o aborto da execuo:
ex: trap "" 1 2 3
b) podemos executar comandos aps a recepo desses sinais:
ex: trap "echo INTERRUPT rm /tmp/tempfileexit 1"
1 2 3
c) podemos restaurar o comportamento standard de recepo desses sinais:
ex: trap 1 2 3
4.7. 'TPUT' - Programas atraentes
Como o nosso leitor j se deve ter apercebido, as mquinas UNIX permitem acesso atravs de diversos
terminais. Isto : para se aceder a estas mquinas tanto se pode utilizar um terminal DEC VT100, como
um TELEVIDEO 925, ou um IBM PC ou qualquer outro das vrias dezenas (se no centenas) de
terminais disponveis no mercado. E todos tm caracteristicas diferentes.
7/21/2019 Manual de Programao Shell (2)
49/59
Um programador que se preze gosta de controlar o que o utilizador v no ecr. Assim apaga o ecr, move
o cursor, utiliza as capacidades de mostrar caracteres em "standout", "reverse", "blink" e "underline", etc.
Desde que se saiba partida qual o terminal que vai ser usado, no difcil fazer isto: basta consultar o
manual deste e enviar as sequncias de caracteres (normalmente come,cadas por ESCAPE) que a vm
descritas.
Mas se partida no se sabe qual o terminal a comeam os trabalhos. preciso preparar o programa para
trabalhar com cada um dos terminais e alter-lo sempre que surja um novo... Nada prtico.
Felizmente isto no necessrio. O comando "tput", serve precisamente para tornar os programas
independentes do terminal em que so invocados. A compreenso de como fuciona este comando implica
o conhecimento da base de dados TERMINFO, pelo que no nos alongaremos demasiado no seu estudo.
Importa principalmente indicar a forma de o utilizar, o que ser feito pela tabela seguinte e pelos
exemplos que se lhe seguem.
FUNO 1: ARG OUTROS ARGUMENTOS
Apagar ecrn clear
Mover cursor cup nova posio
Cursor invisivel civis
Cursor normal cnorm
Entrar em "bold" smso
Sair de "bold" rmso
Entrar em "underline" smul
Sair de "underline" rmul
Ligar impressora[6] mc5
Desligar impressora mc4
Figura 55.tput - alguns parmetros e significado
Se quisermos desligar o cursor devemos portanto executar
7/21/2019 Manual de Programao Shell (2)
50/59
$ tput civis
e se quisermos apagar o ecr, deixando o cursor no meio daquele podemos invocar
$ tput clear tput cup 12 40
4.8. Funes
4.8.1 A necessidade de simplificao
medida em que os programas se vo tornando maiores, os programadores lutam com crescentes
dificuldades para dominar a sua complexidade. Este tipo de problemas e as suas hipotticas solues tm
vindo a ser discutidos ao longo do tempo por diversos peritos de anlise e programao e esta discusso
no cabe neste pequeno curso. No entanto, todos so unnimes em que uma das formas mais simples de
combater as dificuldades causadas pelo tamanho dos programas sub-dividir a tarefa a realizar em sub-
tarefas interligadas, que por sua vez se sub-dividiro noutras sub-tarefas, e assim sempre at que se atinja
um nvel compreensvel para o computador.
Para exemplificar imagine que tem de programar um robot para executar um telefonema. Nada simples. O
que temos a fazer sub-dividir o telefonema em pequenos passos, as diversas sub-tarefas: (1) levantar
auscultador, (2) aguardar sinal de marcar, (3) colocar moedas, (4) marcar nmero, (5) aguardar resposta e
finalmente (6) conversar.[7]Vamos agora avaliar a sub-tarefa 3 - colocar moedas. Poderiamos sub-dividi-
la ainda em (7) meter a mo ao bolso, (8) tirar moedas, (9) largar moedas na calha. Por sua vez, qualqueruma das tarefas que compem a tarefa 3 pode ser sub-dividida. A tarefa 7, por exemplo: (10) levantar
ombro, (11) encolher brao(12) encostar mo anca, (13) esticar brao at a mo entrar no bolso.
Poderamos continuar assim a quebrar a complexidade da tarefa inicial at atingirmos um nvel que fosse
directamente programvel no robot. Este mtodo torna-se "obrigatrio" quando se quer informatizartrabalhos um pouco mais complexos. Resta agora avaliar como poderemos aplic-lo programao em
shell.
7/21/2019 Manual de Programao Shell (2)
51/59
4.8.2. Funes
Assim como podemos criar novos comandos que podero ser chamados em qualquer altura mo ou
noutro programa podemos tambm criar comandos internos a determinado programa. Estes comandos
internos designam-se por funes. O exemplo que se segue apresenta o caso j contmplado de umprograma para fazer backups, desta vez com a tarefa sub-dividida em funes. Repare-se na
particularidade de as instruces relativas s funes estarem colocadas cabea do programa:
# userbackup - verso II (estruturada)
# backup de ficheiros pedidos pelos utilizadores
# ficheiros temporrios
RROS=/tmp/tf1$$
LISTA=/tmp/tf2$$
CORREIO=/tmp/tf3$$
# crialista: funo para criar lista de ficheiros e directrios
crialista () {
true > $LISTA
find / -name backup.lst -print | while read listfile
do
echo "encontrado ficheiro $listfile. processando... "
true > $ERROS
set `ls -sl $listfile`
dono=$4
echo "validao dos dados em $listfile... " while read filename
do
if [ -f $filename -o -d $filename ]
then
if [ -s $filename ]
then
echo $filename >> $LISTA
else
echo "*** AVISO: $filename est vazio." >> $ERROS
fi
else
echo "*** ERRO: $filename no vlido." >> $ERROS fi
done < $listfile
if [ -s $ERROS ]
then
mostraerros
fi
done
}
# mostraerros: funo para enviar correio ao dono do ficheiro
# sub-tarefa da funo crialista
mostraerros () {
echo "encontrados erros_. correio para o dono: $dono"
echo "\n\n\nRelatrio do backup de `date`\n\n" > $CORREIO
cat $ERROS >> $CORREIO
mail $dono < $CORREIO
}
7/21/2019 Manual de Programao Shell (2)
52/59
( contiuna na pgina seguinte )
# arquiva: funo que realiza o arquivo
arquiva () {
echo "criao do arquivo..."
tar cvFf $LISTA /tmp/tar
}
# limpa: remoo dos temporrios
limpa () {
rm $ERROS $LISTA $CORREIO 2> /dev/null
}
# CORPO DO PROGRAMA
crialista
arquiva
limpa
# FIM DO PROGRAMA
Figura 56.userbackup2 - verso estruturada dos backups
4.8.3. Argumentos e valor de sada
Tal como os programas independentes as funes podem ter argumentos e estados, de sada. A nica
diferena est na devoluo deste ltimo, que em vez de ser declarado com "exit nnn" deve s-lo com
"return nnn". Para todos os efeitos uma funo pode ser tratada tal como um programa externo:
# cdigo relativo funo
func () {
# utilizao dos parmetros, exemplificada com echo
echo $1 $2 $3
# devoluo de exit status, neste exemplo
# condicionado pela existncia de determinado ficheiro
if [ -f $filename ]
then return 0
else
return 1
fi
}
# CORPO DO PROGRAMA
.
.
.
if func arg1 arg2 arg3
7/21/2019 Manual de Programao Shell (2)
53/59
then
# ficheiro existe
.
.
.
else
# ficheiro no existe
.
.
.
fi
Figura 57.utilizao de funes
5. E AGORA?
Com os conhecimentos adquiridos neste curso, o leitor (que pode passar a considerar-se desde j um
programador se ainda no o era) tem capacidade de criar programas bastante potentes. No entanto
natural que venha a encontrar situaes em que o shell, como linguagem de programao insuficiente.
Normalmente, isto acontece por falta de rapidez na execuo dos programas. No h nada que substitua
uma boa linguagem de programao como o C[8] mas h alguns utilitrios que podem ajudar ao
programador de shell. O estudo destes programas no pode ser feito neste curso mas nosso dever fazer-
lhes referncia: awk, sed, cut, paste, join, etc.
Para terminar duas recomendaes: no deixe de fazer os exerccios, leia os livros da bibliografia (alguns,
pelo menos), e boa sorte.
6. EXERCCIOS
Exerccio - I
Escreva um script que indique apenas a data em tamanho grande (com a utilizao do comando "banner").
Tenha cuidado para no dar ao seu script o mesmo nome que tem o comando do UNIX.
7/21/2019 Manual de Programao Shell (2)
54/59
Exerccio - II
Altere o seu ".profile" de modo a manter uma lista em ficheiro com as vrias horas de entrada no sistema.
Isto : cada vez que voc entre no sistema, quando o shell executa o ".profile" devem ser executadas
instruces para guardar esta informao.
Exerccio - III
Escreva um programa que envie uma nota para diversos utentes. A nota deve ser pedida por teclado. Os
utentes devem receber um correio a nota com o seguinte formato:
Caro colega:
* texto a pedir pelo teclado *Sem outro assunto, * logname*
Figura 58.Resultado do programa 'memo'
O programa executar do seguinte modo:
$ memo Joao Ana Vitor MSilvaIntroduza o texto terminando com ^d:
> Estive hoje numa reunio com o chefe da informtica
> da S.V., que me disse que...
.
.
> ^D
Confirma o envio para: Joao Ana Vitor MSilva ? s
Envio...
Terminado.
$
Figura 59.Utilizao do comando 'memo'
Os utentes recebero um correio com o seguinte teor:
From Manel Tue Jan 23 13:00 GMT 1990
7/21/2019 Manual de Programao Shell (2)
55/59
Caro Colega:
Estive hoje numa reunio com o chefe da informtica
da S.V., que me disse que...
.
.
Sem outro assunto, Manel
Figura 60.Correio do comando 'memo'
Exerccio - IV
Mude a sua prompt para "CMD: ".
Exerccio - V
Sem usar a opo -R do comando "ls" faa um script que execute uma visualizao recursiva de um
directrio e dos seus sub-directrios.
Exerccio - VI
preciso fazer backups. Queremos usar uma tape mas ficheiros do directrio que queremos guardar
(chamemos-lhe X) no cabem todos. A soluo deixar de fora os programas executveis. Mas os scripts
de shell devem ir, pelo que no basta usar o "[ -x $file ]". Como o fazer?
Exerccio - VII
Realize um programa em shell que permita fazer toda a gesto de uma lista telefnica, desde a adio de
registos, consulta por nome, at impresso da lista numa impressora. Esmere-se, e faa um programa
bonito e bem arranjadinho.
Exerccio - VIII
Voc o chefe de um grupo de trabalho. Precisa de enviar para o seu grupo muitas comunicaes e est
farto de enumerar sempre todos os nomes dos seus colegas ao mail. Podia ser preguioso e criar um script
assim:
mail Joao Joana Alberto Alberta Antnio Antnia \
Guilherme Guilhermina Mrio Maria Carlos Carla \
7/21/2019 Manual de Programao Shell (2)
56/59
Manuel Manuela
Mas a preguia no um dos seus defeitos. Voc decidiu criar um script, ao qual chama "gmail", que
funciona exactamente como o mail, mas recebe nos seus argumentos nomes de grupos, em vez de nomes
de utilizadores.
Exerccio - IX
Crie um programa que mova todos os ficheiros com permisso de execuo (que se presumem ser
programas) para o directrio $HOME/bin.
Exerccio - X
Aproveite o programa que j fez num dos exercicios anteriores para realizar outro que permita fazer
backups de qualquer directrio ou lista de ficheiros a fornecer pelo utilizador, e permitir tambm realizar
a reposio dos ficheiros contidos em tape. O programa deve apresentar incialmente o seguinte menu:
1. Cpias de Segurana
2. Restauro de Dados 3. Avaliao Prvia
4. Esclarecimentos
5. Sair
Indique a sua escolha:
Figura 61.Men do programa de Backups.
A opo "esclarecimentos" servir apenas para dizer ao utilizador o que fazem cada uma das outraopes. A opo "Avaliao prvia" servir para calcular o nmero de tapes necessrias para o backup
de determinada lista de ficheiros. Aconcelha-se a que seja usado o "cpio" para
arquivar os dados. Assuma que as tapes usadas so todas do mesmo tamanho e que tm ou 40 Mbytes ou
150 MBytes, conforme a mquina em que est a trabalhar.
Exerccio - XI
Sem utilizar o comando "wc" conte os ficheiros existentes no seu directrio. Automticamente.
7/21/2019 Manual de Programao Shell (2)
57/59
7. BIBLIOGRAFIA
UNIX User's Guide, AT&T
UNIX User's Reference Manual, AT&T
UNIX, The Complete Reference, Stephen Coffin, McGraw Hill
The UNIX System Guidebook, 2nd Ed., Peter P. Silvester, Springer-Verlag
Advanced Programmer's Guide to UNIX System V, Rebecca Thomas, Lawrence Rogers,
Jean Yates, McGraw Hill
UNIX System Programming, Keith Haviland, Ben Salama, Addison-Wesley
8. NDICE
ABERTURA..................................................................................................................... 1
PROGRAMAO EM SHELL....................... ......................... ........................ ................. 2
1. SHELL SCRIPTS........................ ......................... ......................... .................... 2
1.1 Criao de um pequeno shell script........................................................ 2
1.2. Criao de um directrio 'BIN' para conter os scripts............................. 4
1.3. Avisos acerca dos nomes dos shell scripts............................................. 5
2. VARIVEIS..................................................................................................... 7
2.1. Parmentos posicionais................................... ........................ ............. 7
2.2. Parmetros especiais.................................. ......................... ................ 12
2.3 Variveis identificadas........................................ ......................... ......... 16
2.4. Afecto de variveis........................ ......................... ......................... 17
7/21/2019 Manual de Programao Shell (2)
58/59
3. PASSO EM FRENTE...................... ......................... ......................... ................ 23
3.1 Comentrios........................... ......................... ........................ ............. 23
3.2 Redireccionamento interno.................................................................... 24
3.3 Utilizao do 'ED' dentro de um script.................................................... 25
3.4.Estados de saida - Exit Status................................................................ 283.5. Ciclos.................................................................................................. 28
3.6 O caixote do lixo: '/dev/null'................................................................... 35
3.7 Execuo Condicional......................... ......................... ........................ . 35
3.8 'TEST': Um comando til....................................................................... 43
3.9. Controlo incondicional: 'BREAK' e 'CONTINUE'.................................. 51
3.10. Aritmtica EXPR..................................... ......................... ................. 52
4. TCNICAS MAIS AVANADAS....................... ........................ ..................... 54
4.1. Resoluo de problemas......................... ......................... ..................... 54
4.2. O comando 'SET'....................... ......................... ........................ ......... 55
4.3. Leitura ficheiros cim o 'WHILE READ'................................................ 56
4.4. A varivel 'IFS'..................... ......................... ......................... ............. 60
4.5. Execuo condicional sem 'IF'.............................................................. 62
4.6. Tratamento de sinais...................... ......................... ......................... .... 64
4.7. 'TPUT' - Programas atraentes......................... ......................... ............ 67
4.8. Funes......................................... ........................ ......................... .... 70
5. E AGORA?....................................................................................................... 75
6. EXERCCIOS.................................................................................................... 76
Exerccio - I............................................................................................... 76
Exerccio - II.............................................................................................. 76
Exerccio - III............................................................................................ 76
Exerccio - IV............................................................................................ 77
Exerccio - V............................................................................................. 78Exerccio - VI............................................................................................ 78
Exerccio - VII........................................................................................... 78
7/21/2019 Manual de Programao Shell (2)
59/59
Exerccio - VIII............................................ ........................ ...................... 78
Exerccio - IX............................................................................................ 79
Exerccio - X.............................................................................................. 79
Exerccio - XI............................................................................................ 80
7. BIBLIOGRAFIA............................................................................................... 818. NDICE............................................................................................................. 82
[1]A menos que a confuso seja desejada.
[2]Ns no somos sexistas. Sempre que falamos no masculino tambm estamos a pensar nas senhoras. Desculpem-nos.
[3]Mais uma vez se nota que isto tanto pode ser feito em programa como interactivamente.
[4]Tambm designadas pos "loops".
[5]Isto pode no dizer muito ao leitor que no programador habitual, mas isso no deve ser motivo para preocupao.
[6]Isto aplica-se aos terminais com duas portras e possibilidade de ligar uma impressora a uma delas.
[7]O leitor poder dizer que podem surgir problemas se utilizarmos um mtodo to simples que ignora factores tais comoa possibilidade de a linha estar impedida mas para exemplo serve.
[8]Isto uma afirmao muito discutivel...