<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//pt_BR">
<HTML>
<HEAD>
 <META http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
 <META NAME="GENERATOR" CONTENT="lfparser_2.27">
 <META NAME="LFCATEGORY" CONTENT="UNIXBasics">
 <TITLE>lf216, UNIXBasics: Programa&ccedil;&atilde;o Shell</TITLE>
<style type="text/css">
<!--
 td.top {font-family: Arial,Geneva,Verdana,Helvetica,sans-serif; font-size:12 }
 pre { font-familiy:monospace,Courier }
 p.cl { color:#EE9500 }
 a.nodec { text-decoration:none }
 p.trans { font-size:8pt; text-align:right }
 p.clbox { width:50%; alignment:center; background-color:#FFD700; 
           border-style:none; border-width:medium; border-color:#FFD700; 
           padding:0.5cm;  text-align:center }
 p.code { width:80%; alignment:center; background-color:#aedbe8; 
          border-style:none; border-width:medium; border-color:#aedbe8; 
          padding:0.1cm;  text-align:left }
 p.foot { background-color:#AAAAAA; color:#FFFFFF; border-style:none; 
          border-width:medium; border-color:#AAAAAA; padding:0.5cm ; 
          margin-top:0.1cm; margin-right:1cm; margin-left:1cm; 
          text-align:center }
-->
</style>
 
</HEAD>
<BODY bgcolor="#ffffff" text="#000000">
 <!-- this is generated html code. NEVER use this file for your
 translation work. Instead get the file with the same article number
 and .meta.shtml in its name. Translate this meta file and then
 use lfparser program to generate the final article -->
 <!-- lfparser can be obtained from http://www.linuxfocus.org/~guido/dev/lfparser.html -->

<!-- this is used by a number of tools:
 =LF=AUTHOR: Katja and Guido Socher
 =LF=CAT___: UNIXBasics
 =LF=TITLE_: Programa&ccedil;&atilde;o Shell
 =LF=NUMBER: 216
 =LF=ANAME_: article216.shtml
 -->

<!-- 2pdaIgnoreStart -->

<!-- start navegation bar -->
 <!-- top navegation bar -->
 <TABLE summary="topbar_1" cellspacing="0" cellpadding="0" border="0" align="center" width="90%">
   <TR bgcolor="#2e2292">
     <TD class="top"><TABLE summary="topbar_1_logo" cellspacing="0" cellpadding="0" border="0" width=
       "100%">
         <TR><TD width="319"><IMG src="../../common/images/logolftop_319x45.gif"
           alt="[LinuxFocus-icon]" width="319" height="45" align="left" 
           border="0"></TD>

           <TD class="top">
             <TABLE summary="topbar_1_links" width="100%">
               <TR align="right">
                 <TD class="top"><A class="nodec" href="../index.shtml"><FONT color=
                 "#DDDDDD" size="2">In&iacute;cio</FONT></A> &nbsp;|&nbsp; <A class=
                 "nodec" href="../map.html"><FONT color=
                 "#DDDDDD" size="2">Mapa</FONT></A> &nbsp;|&nbsp; <A class=
                 "nodec" href="../indice.html"><FONT color=
                 "#DDDDDD" size="2">&Iacute;ndice</FONT></A> &nbsp;|&nbsp; <A class="nodec" href="../Search/index.shtml"><FONT color=
                 "#DDDDDD" size="2">Procura</FONT></A> </TD>
               </TR>

               <TR align="right">
                 <TD class="top">
                   <HR width="100%" noshade size="1">
                 </TD>
               </TR>
             </TABLE>
           </TD>
         </TR>
       </TABLE>
     </TD>
   </TR>
 </TABLE>
 <!-- end top navegation bar -->
 <!-- blue bar -->
 <TABLE summary="topbar_2" cellspacing="0" cellpadding="0" border="0" align="center"
 width="90%">
   <TR bgcolor="#00ffff">
     <TD><IMG src="../../common/images/transpix.gif" width="1" height=
     "2" alt=""></TD>
   </TR>
 </TABLE>
 <!-- end blue bar -->
 <!-- bottom navegation bar -->
 <TABLE summary="topbar_3" cellspacing="0" cellpadding="0" border="0" align="center"
 width="94%">
   <TR bgcolor="#000000">
     <TD>
       <TABLE summary="topbar_3_links" cellspacing="0" cellpadding="1" border="0" width=
       "100%">
         <TR align="center">
           <TD WIDTH="20%"><A class="nodec" href="../News/index.shtml"><FONT color=
           "#FFFFFF">Novidades</FONT></A> </TD>
           <TD WIDTH="5%"><FONT color="#FFFFFF">|</FONT> </TD>
           <TD WIDTH="20%"><A class="nodec" href="../Archives/index.html"><FONT color=
           "#FFFFFF">Arquivos</FONT></A> </TD>
           <TD WIDTH="5%"><FONT color="#FFFFFF">|</FONT> </TD>
           <TD WIDTH="20%"><A class="nodec" href="../Links/index.shtml"><FONT color=
           "#FFFFFF">Links</FONT></A> </TD>
           <TD WIDTH="5%"><FONT color="#FFFFFF">|</FONT> </TD>
           <TD WIDTH="20%"><A class="nodec" href="../aboutus.html"><FONT color=
           "#FFFFFF">Sobre LF</FONT></A> </TD>
         </TR>
       </TABLE>
     </TD>
   </TR>
 </TABLE>
 <!-- end bottom navegation bar -->
<!-- stop navegation bar -->

<!-- SSI_INFO -->

<!-- tr_staticssi include virtual -->
<!-- tr_staticssi exec cmd -->
<!-- addedByLfdynahead ver 1.1 --><TABLE ALIGN="right" border=0><TR><TD ALIGN="right"><FONT SIZE="-1" FACE="Arial,Helvetica">Este artigo est&aacute; dispon&iacute;vel em: <A href="../../English/September2001/article216.shtml">English</a> &nbsp;<A href="../../Castellano/September2001/article216.shtml">Castellano</a> &nbsp;<A href="../../Deutsch/September2001/article216.shtml">Deutsch</a> &nbsp;<A href="../../Francais/September2001/article216.shtml">Francais</a> &nbsp;<A href="../../Nederlands/September2001/article216.shtml">Nederlands</a> &nbsp;<A href="../../Portugues/September2001/article216.shtml">Portugues</a> &nbsp;<A href="../../Turkce/September2001/article216.shtml">Turkce</a> &nbsp;</FONT></TD></TR></TABLE><br>
 


<!-- SSI_INFO STOP -->
<!-- 2pdaIgnoreStop -->

<!-- SHORT BIO ABOUT THE AUTHOR -->
<TABLE ALIGN=LEFT BORDER=0  WIDTH="190" >
<TR>
<TD>

<!-- 2pdaIgnoreStart -->
<!-- PALM DOC -->
<TABLE BORDER=0 hspace=4 vspace=4> <TR> <TD>
<font size=1> <img src="../../common/images/2doc.gif" width=34 align=left border=0 height=22 alt="convert to palm"><a href="http://cgi.linuxfocus.org/cgi-bin/2ztxt">Convert to GutenPalm</a><br>or <a href="http://cgi.linuxfocus.org/cgi-bin/2pda">to PalmDoc</a></font>
</TD> </TR> </TABLE>
<!-- END PALM DOC -->
<!-- 2pdaIgnoreStop -->
<br>
<IMG
src="../../common/images/KatjaAndGuido.jpg" alt= "[Photo of the Authors]"
height="150" width="168">
<BR>por  Katja and Guido Socher <br> <small>&lt;katja(at)linuxfocusorg, guido(at)linuxfocus.org&gt;</small>
<BR><BR>
<I>Sobre o autor:</I><BR>
<P>Katja &eacute; a editora germ&acirc;nica de LinuxFocus. Ela gosta de Tux, filmes
&amp; fotografia e o mar. A sua p&aacute;gina pessoal encontra-se <A href=
"http://linuxfocus.org/~katja/">aqui</A>.</P><P>Guido &eacute; um fan de Linux desde a muito e gosta do Linux porque ele foi
criado por pessoas honestas e de mentalidade aberta. &Eacute; uma das razões
porque o chamamos open source. A sua p&aacute;gina pessoal esta no <A
href="http://linuxfocus.org/~guido/">linuxfocus.org/~guido</A>.</P>
<!-- TRANSLATED TO pt -->
<BR><BR><I>Traduzido para Portugu&ecirc;s por:</I><BR>
Patrick Carpalhoso  <small>&lt;carpalhoso(at)mail.telepac.pt&gt;</small>
<br>
<!-- TRANSLATED TO STOP -->
<BR><i>Conte&uacute;do</i>:
<UL>
  <LI><A HREF="#216lfindex0">Porqu&ecirc; programa&ccedil;&atilde;o shell ?</A></LI>
  <LI><A HREF="#216lfindex1">Criar um script</A></LI>
  <LI><A HREF="#216lfindex2">Coment&aacute;rios</A></LI>
  <LI><A HREF="#216lfindex3">Vari&aacute;veis</A></LI>
  <LI><A HREF="#216lfindex4">Comandos Shell e estruturas de control</A></LI>
  <LI><A HREF="#216lfindex5">Exemplos</A></LI>
  <LI><A HREF="#216lfindex6">Debugging</A></LI>
  <LI><A HREF="#216lfindex7">Refer&ecirc;ncias</A></LI>
  <LI><A HREF="http://cgi.linuxfocus.org/cgi-bin/lftalkback?anum=216&amp;lang=pt">Forma de respostas para este artigo</A></LI>
</UL>

</TD></TR></TABLE>
<!-- HEAD OF THE ARTICLE -->
<br>&nbsp;
<H2>Programa&ccedil;&atilde;o Shell</H2>
 <IMG
src="../../common/images/illustration216.jpg" width="199" height="150"
alt="[Illustration]" hspace="10">
<!-- ABSTRACT OF THE ARTICLE -->
<P><i>Abstrato</i>:
<P>
 Neste
artigo iremos explicar como escrever pequenos scripts shell e dar v&aacute;rios
exemplos.

    
<br><br><!-- HR divider --><table width="300" align="center" border="0">
<tr>
  <td bgcolor="#8282e0"><IMG src="../../common/images/transpix.gif" width="1" height="2" alt=""></td>
</tr>
</table>
<!-- BODY OF THE ARTICLE -->


    <A NAME="216lfindex0">&nbsp;</A>
<H2>Porqu&ecirc; programa&ccedil;&atilde;o shell ?</H2>
 Apesar existirem varias interfaces
graphicas dispon&iacute;veis para Linux o shell continua a ser uma ferramenta muita
eficiente. O shell n&atilde;o &eacute; s&oacute; uma colec&ccedil;&atilde;o de comandos mas uma verdadeira boa
linguagem de programa&ccedil;&atilde;o.  Com ele voc&ecirc; pode automatizar numerosas
tarefas, o shell &eacute; muito bom para tarefas de administra&ccedil;&atilde;o de sistema, voc&ecirc;
pode muito rapidamente testar se as suas ideias funcionam o que torna muito
&uacute;til para uma prototipagem simples e &eacute; muito &uacute;til para pequenos utilit&aacute;rios que
executam tarefas relativamente simples onde a efici&ecirc;ncia &eacute; menos importante que
o conforto da configura&ccedil;&atilde;o, manuten&ccedil;&atilde;o e portabilidade.<BR> Ent&atilde;o vamos ver
como ele funciona: <BR>

    <A NAME="216lfindex1">&nbsp;</A>
<H2>Criar um script</H2>
 Existem muitos shells diferentes dispon&iacute;veis para
Linux mas habitualmente o bash (bourne again shell) &eacute; utilizado para
programa&ccedil;&atilde;o shell porque ele &eacute; gr&aacute;tis e &eacute; f&aacute;cil de utilizar. De modo que todos
os scripts que iremos  escrever neste artigo utiliza o bash (mas na maior parte
do tempo funciona tamb&eacute;m com a sua velha irm&atilde;, o bourne shell).<BR> Para
escrever os nossos programas shell podemos utilizar qualquer editor de texto,
ex: nedit, kedit, emacs, vi... como em qualquer outra linguagem de
programa&ccedil;&atilde;o.<BR> O programa tem de come&ccedil;ar com a linha seguinte (deve ser a
primeira linha no ficheiro):<BR>

<PRE> #!/bin/sh

</PRE> Os caracteres #! informam o sistema que o primeiro argumento que segue
na linha &eacute; o programa utilizado para executar este ficheiro.  Neste caso
/bin/sh &eacute; o shell que utilizamos.<BR> Depois de escrever e gravar o script &eacute;
necess&aacute;rio tornar-lo execut&aacute;vel para o poder utilizar.<BR> Para tornar um
script execut&aacute;vel escreva<BR> chmod +x nomeficheiro<BR> Ent&atilde;o pode executar o seu
script escrevendo: <TT>./nomeficheiro</TT> <BR>

    <A NAME="216lfindex2">&nbsp;</A>
<H2>Coment&aacute;rios</H2>
 Na programa&ccedil;&atilde;o shell os coment&aacute;rios come&ccedil;am com # e
v&atilde;o at&eacute; o fim da linha. Recomendamos a utiliza&ccedil;&atilde;o dos coment&aacute;rios. Se t&ecirc;m
coment&aacute;rios e que n&atilde;o utiliza um script desde um certo tempo voc&ecirc; saber&aacute;
imediatamente do que se se trata e como funciona.<BR>

    <A NAME="216lfindex3">&nbsp;</A>
<H2>Vari&aacute;veis</H2>
 Como nas outras linguagens de programa&ccedil;&atilde;o n&atilde;o se pode
viver sem vari&aacute;veis.  Na programa&ccedil;&atilde;o shell todas as vari&aacute;veis s&atilde;o de tipo
string e n&atilde;o &eacute; necess&aacute;rio declara-las. Para atribuir um valor a uma vari&aacute;vel
basta escrever: <PRE>vari&aacute;vel=valor </PRE> Para ler o conte&uacute;do de uma vari&aacute;vel
basta colocar um cifr&atilde;o antes da vari&aacute;vel; <PRE>#!/bin/sh
# atribui um valor:
a="hello world"
# e agora escreve o conte&uacute;do de "a":
echo "A &eacute;:" echo $a </PRE> Escreva estas linhas no seu editor de texto e grave
com o nome first. Ponha o script execut&aacute;vel escrevendo chmod +x first no shell
e executa escrevendo ./first<BR> O script ira unicamente escrever:  <PRE>A &eacute;:
hello world </PRE> Por vezes &eacute; poss&iacute;vel confundir os nomes das vari&aacute;veis com o
resto do texto: <PRE>num=2 echo "isto &eacute; o $numnd" </PRE> Isto n&atilde;o vai imprimir
"isto &eacute; 2nd" mas "isto &eacute; " porque o shell vai procurar por uma vari&aacute;vel chamada
numnd que n&atilde;o tem valor nenhum. Para dizer ao shell que estamos a fazer refer&ecirc;ncia
a vari&aacute;vel num temos que usar as chavetas: <PRE>num=2 echo "isto &eacute; o ${num}nd"
</PRE>Desta forma vai escrever: isto &eacute; o 2nd<BR> <BR> Existem vari&aacute;veis
que s&atilde;o automaticamente inicializadas. Iremos discutir delas mais abaixo a
primeira utiliza&ccedil;&atilde;o.  <BR> <BR> Se necessita de manipular
expressões matem&aacute;ticas ent&atilde;o precisa de utilizar programas como expr (ver a
tabela seguinte).<BR>Apesar das vari&aacute;veis de shell normais ser unicamente
validas em programas shell existem tamb&eacute;m vari&aacute;veis de ambiente. A vari&aacute;vel
precedida com a palavra-chave export &eacute; uma vari&aacute;vel de ambiente. N&atilde;o iremos
mais falar sobre elas sabendo que elas s&atilde;o normalmente utilizadas em scripts de
login.

    <A NAME="216lfindex4">&nbsp;</A>
<H2>Comandos Shell e estruturas de control</H2>
 Existem 3 categorias de
comandos que podem ser utilizadas em scripts shell:<BR> <BR> <B>1)Comandos
Unix:</B><BR> Se bem que um script shell pode utilizar qualquer comando unix existem
comandos que s&atilde;o utilizados mais vezes que outros. Esses comandos podem ser
descritos como comandos para manipula&ccedil;&atilde;o de ficheiro e de texto.<BR>

    <TABLE bgcolor="#aaaaff" border="1" align="center"> <TR> <TH
width="30%">Syntax de comandos</TH>

        <TH>Objectivo</TH> </TR>

      <TR> <TD>echo "algum texto"</TD>

        <TD>escreve algum texto no ecr&atilde;</TD> </TR>

      <TR> <TD>ls</TD>

        <TD>lista ficheiros</TD> </TR>

      <TR> <TD>wc -l ficheiro<BR> wc -w ficheiro<BR> wc -c ficheiro</TD>

        <TD>conta as linhas num ficheiro ou<BR>conta o numero de palavras<BR>
            conta os numeros caracteres
</TD>
</TR>

      <TR> <TD>cp ficheiroorigem ficheirodestino</TD>

        <TD>copia ficheiroorigem para ficheirodestino</TD> </TR>

      <TR> <TD>mv nomeantigo novonome</TD>

        <TD>renomeia ou move um ficheiro</TD> </TR>

      <TR> <TD>rm ficheiro</TD>

        <TD>apaga um ficheiro</TD> </TR>

      <TR> <TD>grep 'qualquercoisa' ficheiro</TD>

        <TD>procura por strings num ficheiro<BR> Exemplo: grep 'qualquercoisa'
ficheiro.txt</TD> </TR>

      <TR> <TD>cut -b colnum file</TD>

        <TD>extrai dados de uma coluna fixa de texto<BR> Exemplo: extrai
caracteres da posi&ccedil;&atilde;o 5 a 9<BR> cut -b5-9 file.txt<BR> N&atilde;o confundir com o
comando "cat" que faz uma coisa completamente diferente</TD> </TR>

      <TR> <TD>cat ficheiro.txt</TD>

        <TD>escreve o conte&uacute;do de ficheiro.txt no stdout (seu ecr&atilde;)</TD> </TR>

      <TR> <TD>file ficheiroqualquer</TD>

        <TD>descreve qual &eacute; o tipo do ficheiro ficheiroqualquer</TD> </TR>

      <TR> <TD>read var</TD>

        <TD>pede ao utilizador para escrever e coloca numa vari&aacute;vel (var)</TD>
</TR>

      <TR> <TD>sort ficheiro.txt</TD>

        <TD>ordena as linhas no ficheiro.txt</TD> </TR>

      <TR> <TD>uniq</TD>

        <TD>remove as linhas duplicadas, utilizado em combina&ccedil;&atilde;o com sort visto
uniq remover unicamente linhas duplicadas consecutivas<BR> Exemplo: sort
ficheiro.txt | uniq<BR> </TD> </TR>

      <TR> <TD>expr</TD>

        <TD>faz matem&aacute;tica no shell<BR> Exemplo: adiciona 2 e 3<BR> expr 2 "+"
3</TD> </TR>

      <TR> <TD>find</TD>

        <TD>procura ficheiros<BR> Exemplo: procura por nome:<BR> find . -name
ficheiro -print<BR> Este comando tem muitas possibilidades e op&ccedil;ões. &Eacute;
demasiado para ser explicado ao pormenor neste artigo.</TD> </TR>

      <TR> <TD>tee</TD>

        <TD>escreve os dados para stdout (seu ecr&atilde;) e para um ficheiro<BR>
Normalmente utilizado da seguinte forma:<BR> umcomando | tee ficheiroout<BR>
Ele escreve o output de umcomando para o ecr&atilde; e para o ficheiro
ficheiroout</TD> </TR>

      <TR> <TD>basename ficheiro</TD>

        <TD>devolve o nome do ficheiro de um determinado ficheiro e remove o
caminho<BR> Exemplo: basename /bin/tux<BR> devolve unicamente tux</TD> </TR>

      <TR> <TD>dirname ficheiro</TD>

        <TD>devolve unicamente o nome da directoria de um determinado nome e
remove o nome do ficheiro<BR> Exemplo: dirname /bin/tux<BR> devolve unicamente
/bin</TD> </TR>

      <TR> <TD>head ficheiro</TD>

        <TD>escreve umas linhas desde o inicio do ficheiro</TD> </TR>

      <TR> <TD>tail file</TD>

        <TD>escreve umas linhas desde o fim do ficheiro</TD> </TR>

      <TR> <TD>sed</TD>

        <TD>sed &eacute; basicamente um programa de pesquisa e substitui&ccedil;&atilde;o. Ele l&ecirc;
texto de um input standard (ex desde um pipe) e escreve o resultado para stdout
(normalmente o ecr&atilde;). O padr&atilde;o de pesquisa &eacute; uma express&atilde;o regular (ver
refer&ecirc;ncias). Esse padr&atilde;o de pesquisa n&atilde;o deve ser confundido com a syntax da
wildcard do shell. Para substituir a string linuxfocus por LinuxFocus num
ficheiro texto fa&ccedil;a: <BR> cat ficheiro.txt | sed 's/linuxfocus/LinuxFocus/'
&gt; novoficheiro.txt<BR> Isto substitui a primeira ocur&ecirc;ncia da string
linuxfocus em cada linha com LinuxFocus. Se existirem linhas onde linuxfocus
apare&ccedil;a varias vezes e que queira substituir todos fa&ccedil;a:<BR> cat ficheiro.txt |
sed 's/linuxfocus/LinuxFocus/g' &gt; novoficheiro.txt<BR> </TD> </TR>

      <TR> <TD>awk</TD>

        <TD> A maior parte das vezes awk &eacute; utilizado para extrair campos de uma
linha de texto. O separador por defeito &eacute; espa&ccedil;o. Para definir um outro utiliza
a op&ccedil;&atilde;o -F.  <PRE> <SMALL>cat ficheiro.txt | awk -F, '{print $1 "," $3 }'
</SMALL> </PRE> Neste caso estamos a utilizar a virgula (,) como separador de
campos e escrevemos a primeira e terceira coluna ($1 $3). Se ficheiro.txt tiver
linhas como: <PRE> <SMALL>Adam Bor, 34, India Kerry Miller, 22, USA </SMALL>
</PRE> ira dar como resultado: <PRE> <SMALL>Adam Bor, India Kerry Miller, USA
</SMALL> </PRE>O awk permite fazer muita mais coisas mas esta &eacute; a utiliza&ccedil;&atilde;o mais
frequente.  </TD> </TR> </TABLE> <BR> <BR> <B>2) Conceitos:
Pipes, redirecionamento e backtick</B><BR> N&atilde;o s&atilde;o realmente comandos mas s&atilde;o
conceitos muito importantes.<BR>  <BR> <B>pipes</B> (|) envia o output (stdout)
de um programa para o input (stdin) de um outro programa.<BR> <PRE> grep "hello"
 ficheiro.txt | wc -l </PRE> procura as linhas com a string hello no
ficheiro.txt e conta as linhas.<BR> O output do comando grep &eacute; utilizado como
input para o comando wc. Dessa forma voc&ecirc; pode concatenar os comandos que queira
(nos limites do razo&aacute;vel). <BR> <BR> <B>redirecionamento</B>: escreve o output
de um comando para um ficheiro ou adiciona dados a um ficheiro<BR>
&gt; escreve o output para um ficheiro e sobrepõem o ficheiro
antigo caso ele existir<BR> &gt;&gt; adiciona dados a um ficheiro (ou cria um
novo se ele ainda n&atilde;o existir mas nunca sobrepõem nada).<BR> <BR>
<B>Backtick</B><BR> O output de um comando pode ser utilizado como argumento da
linha de comandos (n&atilde;o stdin como anteriormente, os argumentos da linha de
comandos s&atilde;o qualquer string que voc&ecirc; pode especificar depois de um comando
como nomes de ficheiros e op&ccedil;ões) para um outro comando. Voc&ecirc; pode tamb&eacute;m
utiliza-lo para definir o output de um comando para uma vari&aacute;vel. <BR> O
comando <PRE> find . -mtime -1 -type f -print </PRE> procura todos os ficheiros
que foram modificados nas ultimas 24 horas (-mtime -2 significaria 48 horas).
Se voc&ecirc; quer armazenar esse ficheiros num arquivo tar (ficheiro.tar) a syntax
para o tar teria de ser: <PRE> tar xvf ficheiro.tar ficheiro1 ficheiro2 ...
</PRE> Em vez de escrever isso tudo, voc&ecirc; pode combinar 2 comandos (find e tar)
utilizando backticks. Tar ira aquivar todos os ficheiro que find escreveu:
<PRE> #!/bin/sh
# Backticks (`)  n&atilde;o plicas ('):
tar -zcvf ultimamod.tar.gz `find . -mtime -1 -type f -print` </PRE> <BR>
<B>3) Estruturas de control</B><BR> A instru&ccedil;&atilde;o <B>"if" </B>testa se uma condi&ccedil;&atilde;o
&eacute; verdadeira (c&oacute;digo retorno &eacute; 0, verdadeiro). Se for isso a parte "then" &eacute;
executado:
<PRE>
if ....; then
   ....
elif ....; then
   ....
else
   ....
fi
</PRE>
A maior parte das vezes um comando especial chamado test &eacute; utilizado dentro de
uma instru&ccedil;&atilde;o if. Ele pode ser utilizado para comparar strings ou testar se um
ficheiro existe, se ele pode ser lido etc... <BR>
O comando "test" &eacute; escrito
com as par&ecirc;nteses rectos " [ ] ". Nota que o espa&ccedil;o &eacute; significativo aqui:
Certifica-se que tenha sempre um espa&ccedil;o entre as par&ecirc;nteses rectos. Exemplos:
<PRE>
[ -f "umficheiro" ] : Testa se umficheiro &eacute; um ficheiro.
[ -x "/bin/ls" ]    : Testa se /bin/ls exista e se &eacute; um execut&aacute;vel.
[ -n "$var" ]       : Testa se a the vari&aacute;vel $var tem algo.
[ "$a" = "$b" ]     : Testa se as vari&aacute;veis "$a" e "$b" s&atilde;o iguais </PRE>
Executa o comando "man test" para obter uma longa lista de todos os tipos de
operadores de teste para compara&ccedil;ões e ficheiros.<BR>
Utilizar isso num script shell &eacute; facil:
<PRE>
#!/bin/sh
if [ "$SHELL" = "/bin/bash" ]; then
  echo "o seu shell de login &eacute; o bash (bourne again shell)"
else
  echo "o seu shell de login n&atilde;o &eacute; bash mas sim $SHELL"
fi
</PRE>
A vari&aacute;vel $SHELL cont&ecirc;m o nome do shell de login e ela &eacute; testada que &eacute;
comparada com a string "/bin/bash" <BR>
<BR>
<B>Atalhos de operadores</B><BR>
As pessoas familiarizadas com C reconhecer&atilde;o a express&atilde;o seguinte:<BR>
<PRE>
[ -f "/etc/shadow" ] &amp;&amp; echo "Este computador utiliza shadow passwords"
</PRE>
Os &amp;&amp; podem ser utilizados como uma curta instru&ccedil;&atilde;o if. A parte direita
&eacute; executada se a parte esquerda for verdadeira. Pode ler isso como AND.
Desta maneira o exemplo &eacute;: "O ficheiro /etc/shadow exista AND o comando &eacute;
executada". O operador OR (||) esta tamb&eacute;m dispon&iacute;vel. Segue um exemplo:
<PRE>
#!/bin/sh
mailfolder=/var/spool/mail/james
[ -r "$mailfolder" ] || { echo "N&atilde;o pode ler $mailfolder" ; exit 1; }
echo "$mailfolder t&ecirc;m um mail de:"
grep "^From " $mailfolder </PRE>
O script testa em primeiro se ele pode ler o
mailfolder. Se for o caso ele escreve a linha "t&ecirc;m um mail" no folder, Se ele
n&atilde;o conseguir ler o ficheiro $mailfolder ent&atilde;o o operador OR entra em ac&ccedil;&atilde;o. Em
Ingl&ecirc;s voc&ecirc; pode ler "Mailfolder readable or exit program". O problema aqui &eacute;
que t&ecirc;m de ter exactamente um comando atras do OR mas precisamos de 2: <BR>
    - escrever uma mensagem de erro <BR>
    - sair do programa <BR>

Para trata-los como um &uacute;nico comando podemos junta-los numa fun&ccedil;&atilde;o an&oacute;nima
utilizando chavetas. As fun&ccedil;ões em geral ser&aacute; explicado mais abaixo. <BR>
Pode-se fazer tudo sem ANDs e ORs utilizando unicamente instru&ccedil;ões if mas as
vezes os atalhos AND e OR s&atilde;o mais pr&aacute;ticos. <BR> <BR>
A instru&ccedil;&atilde;o <B>case</B>
pode ser utilizado para combinar (utilizando os wildcards do shell como * e ?)
uma determinada string em compara&ccedil;&atilde;o a numerosas possibilidades.
<PRE>
case ... in
 ...) faz qualquer coisa aqui;; esac </PRE>
Vejamos um exemplo. O comando file pode testar qual &eacute; o tipo de um ficheiro:
<PRE>
file lf.gz

devolve:

lf.gz: gzip compressed data, deflated, original filename, last modified: Mon
Aug 27 23:09:18 2001, os: Unix </PRE>
Vamos utilizar isto agora para escrever um script chamado <A href=
"../../common/src/article216/smartzip.txt">smartzip</A> que pode descomprimir
bzip2, gzip and zip ficheiros comprimidos automaticamente:
<PRE>
#!/bin/sh
ftype=`file "$1"`
case "$ftype" in
"$1: Zip archive"*)
    unzip "$1" ;;
"$1: gzip compressed"*)
    gunzip "$1" ;;
"$1: bzip2 compressed"*)
    bunzip2 "$1" ;;
*) error "Ficheiro $1 no pode ser descomprimido com smartzip";;
esac </PRE> <BR>
Aqui pode reparar que estamos a utilizar uma vari&aacute;vel especial chamada $1. Essa
vari&aacute;vel cont&ecirc;m o primeiro argumento dado ao programa. Por exemplo executamos <BR>
smartzip articles.zip <BR>
ent&atilde;o $1 ira conter a the string articles.zip <BR> <BR>
A instru&ccedil;&atilde;o <B>select</B> &eacute; uma extens&atilde;o especifica do bash e &eacute; muita
boa para utiliza&ccedil;&atilde;o interactiva. O utilizador por seleccionar uma op&ccedil;&atilde;o entre
uma lista de diferentes valores:
<PRE>
select var in ... ; do
   break
done
....  agora $var pode ser utilizado ....  </PRE>
Vejamos este exemplo: <PRE>
#!/bin/sh
echo "Qual &eacute; o seu SO preferido ?"
select var in "Linux" "Gnu Hurd" "Free BSD" "Other"; do
   break
done
echo "Voc&ecirc; seleccionou $var" </PRE>
O que script faz:
<PRE>
Qual &eacute; o seu SO preferido ?
1) Linux
2) Gnu Hurd
3) Free BSD
4) Other
#? 1
Voc&ecirc; seleccionou Linux </PRE>
No shell voc&ecirc; t&ecirc;m as seguintes <B>instru&ccedil;ões de ciclos</B> dispon&iacute;veis:
<PRE>
while ...; do
 ....
done </PRE>
O <B>ciclo-while</B> sera executada at&eacute; que a express&atilde;o que estamos
a testar ser verdadeira. A palavra-chave "break" pode ser utiliza para
abandonar um ciclo a qualquer altura. Com a palavra-chave "continue" o ciclo
continua com a proxima itera&ccedil;&atilde;o e ignora o resto do corpo do ciclo. <BR> <BR>
O <B>ciclo-for</B> pega numa lista de strings (srings separadas por espa&ccedil;o) e
atribuas a vari&aacute;veis:
<PRE>
for var in ....; do
 ....
done </PRE>
O que sega ira imprimir as letras de A a C no ecr&atilde;:
<PRE>
#!/bin/sh for var in A B C ; do
  echo "var &eacute; $var"
done
</PRE>
Um outro exemplo de script util, chamado showrpm, print uma lista do conte&uacute;do de um pacote RPM:
<PRE> #!/bin/sh
# lista um resumo do conte&uacute;do de um pacote RPM
UTILIZA&Ccedil;&Atilde;O: showrpm rpmficheiro1 # rpmficheiro2 ...
EXEMPLO: showrpm /cdrom/RedHat/RPMS/*.rpm
for rpmpackage in $*; do
  if [ -r "$rpmpackage" ];then
     echo "=============== $rpmpackage =============="
     rpm -qi -p $rpmpackage
  else
     echo "ERRO: n&atilde;o consegue ler o ficheiro file $rpmpackage"
  fi
done </PRE>
Como pode ver a vari&aacute;vel especial, $* que cont&ecirc;m todos os argumentos da linha de comando. Se
voc&ecirc; executar <BR>
showrpm openssh.rpm w3m.rpm webgrep.rpm <BR>
ent&atilde;o $* ira conter as 3 strings openssh.rpm, w3m.rpm e webgrep.rpm. <BR> <BR>
O bash GNU conhece tamb&eacute;m os ciclos-until mas geralmente os ciclos while e for s&atilde;o
suficientes. <BR> <BR>
<B>Utilizando aspas</B><BR>
Antes de passar qualquer
argumento a um programa o shell tenta desenvolver as wildcards e vari&aacute;veis.
Desenvolver significa que as wildcards (ex: *) s&atilde;o substitu&iacute;das pelo o nome do
ficheiro apropriado ou que essa vari&aacute;vel &eacute; substitu&iacute;da pelo o seu conte&uacute;do.
Para mudar esse comportamento voc&ecirc; pode utilizar aspas: Digamos que temos um
numero de ficheiros numa directoria. 2 deles s&atilde;o ficheiros jpg, mail.jpg e
tux.jpg.
<PRE>
#!/bin/sh echo *.jpg </PRE>
Isto ira escrever "mail.jpg tux.jpg".<BR>
Aspas e plicas ira impedir essa expans&atilde;o de wildcard:
<PRE>
#!/bin/sh echo "*.jpg"
echo '*.jpg' </PRE>
Isto ira escrever "*.jpg" 2 vezes.  <BR>
As plicas s&atilde;o mais restritivas. Elas evitam igualmente a expans&atilde;o de
vari&aacute;veis. Aspas evitam a expans&atilde;o de wildcard mas permita a expans&atilde;o de
vari&aacute;veis:
<PRE>
#!/bin/sh
echo $SHELL
echo "$SHELL"
echo '$SHELL'
</PRE>
Isto ira escrever:
<PRE>
/bin/bash
/bin/bash
$SHELL </PRE>
E por fim exista a possibilidade de aceitar significado especial de qualquer caracter fazendo
preceder da backslash:
<PRE>
echo \*.jpg
echo \$SHELL
</PRE>
Isto ira escrever:
<PRE> *.jpg $SHELL </PRE>
<B>Aqui documentos</B><BR>
Aqui documentos &eacute; uma maneira engra&ccedil;ada de enviar varias linhas de texto para um comando.
&Eacute; &uacute;til para escrever um texto de help num script sem ter a necessidade de colocar echo a
frente de cada linha. Um aqui documento come&ccedil;a com &lt;&lt; seguindo de qualquer string que
pode tamb&eacute;m aparecer no fim de um aqui documento.
Aqui <A href= "../../common/src/article216/ren.txt">esta um script de exemplo, chamado ren,</A>
que renomeia multiplos ficheiros e utiliza um aqui documento para o texto de ajuda:
<PRE>
#!/bin/sh
# Temos menos de 3 argumentos. Escreve o texto do help:
if [ $# -lt 3 ] ; then
  cat &lt;&lt;HELP
ren -- renomeia um numero de ficheiros utilizando expressões do sed

UTILIZA&Ccedil;&Atilde;O: ren 'regexp' 'replacement' files...

EXEMPLO: renomeia todos os ficheiros *.HTM para *.html: ren 'HTM$' 'html' *.HTM

HELP exit 0 fi OLD="$1" NEW="$2"
# O comando shift remove um argumento da lista dos argumentos da linha de
# comandos.
shift shift
# $* agora tem todos os ficheiros:
for file in $*; do
   if [ -f "$file" ] ; then
      newfile=`echo "$file" | sed "s/${OLD}/${NEW}/g"`
      if [ -f "$newfile" ]; then
         echo "ERROR: $newfile j&aacute; existe"
      else
         echo "renomeando $file para $newfile ..."
         mv "$file" "$newfile"
      fi
   fi
done </PRE>
&Eacute; o script mais complexo que vimos at&eacute; aqui. Vamos falar um
pouco sobre ele. A primeira instru&ccedil;&atilde;o if testa se temos ao menos 3 par&acirc;metros
na linha de comandos. (A vari&aacute;vel especial $# cont&eacute;m o numero de argumentos).
Se n&atilde;o for o caso, o texto do help &eacute; enviado ao comando cat que por sua vez
mande-o para o ecr&atilde;. Depois de escrever o texto do help sa&iacute;mos do programa. Se
tivermos 3 ou mais argumentos vamos atribuir o primeiro argumento a vari&aacute;vel
OLD e o segundo a vari&aacute;vel NEW. A seguir deslocamos os par&acirc;metros da linha de
comandos 2 vezes para colocar o  terceiro argumento na primeira posi&ccedil;&atilde;o de $*.
Com $* entramos no ciclo for.  Cada um dos argumentos em $* &eacute; atribu&iacute;do um a um
a vari&aacute;vel $file. A&iacute; vamos em primeiro testar se o ficheiro existe realmente e
vamos construir um novo nome de ficheiro utilizando find e sed. Os backticks
s&atilde;o utilizados para  atribuir o resultado para a vari&aacute;vel newfile. Agora temos
tudo o precisamos: O antigo e novo nome do ficheiro. &Eacute; o que utilizamos com o
comando mv para renomear os ficheiros. <BR> <BR>
<B>Fun&ccedil;ões</B><BR> Logo que
voc&ecirc; tenha um programa mais complexo voc&ecirc; ira achar pratico utilizar o mesmo
c&oacute;digo em v&aacute;rios s&iacute;tios e dar-lhe alguma estrutura.  Uma fun&ccedil;&atilde;o tem um aspecto
semelhante a este:

<PRE>
nomedafuncao()
{
 # Dentro do corpo $1 esta o primeiro argumento dado a fun&ccedil;&atilde;o No $2 esta o
 # segundo ...
 corpo
} </PRE>
Tem de "declarar" as fun&ccedil;ões no inicio do script antes de poder utiliza-las. <BR> <BR>
Aqui esta um script chamado <A href = "../../common/src/article216/xtitlebar.txt">
xtitlebar</A> com o qual voc&ecirc; pode mudar o nome de uma janela de um terminal.
Se voc&ecirc; tiver varias janelas abertas &eacute; uma maneira f&aacute;cil de as identificar. O script envia
uma sequ&ecirc;ncia de escape que &eacute; interpretada pelo terminal e que provoca uma mudan&ccedil;a de
nome da barra da janela. O script utiliza a fun&ccedil;&atilde;o chamada help. Como pode ver a fun&ccedil;&atilde;o &eacute;
definida uma vez e utilizada 2 vezes:
<PRE>
#!/bin/sh
# vim: set sw=4 ts=4 et:

help()
{
    cat &lt;&lt;HELP
xtitlebar -- muda o nome de um xterm, gnome-terminal ou kde konsole

UTILIZA&Ccedil;&Atilde;O: xtitlebar [-h] "texto_para_a_janela"

OP&Ccedil;&Otilde;ES: -h help text

EXEMPLO: xtitlebar "cvs"

HELP
    exit 0
}

# Se ocorrer algum erro ou se for introduzido -h chamamos a fun&ccedil;&atilde;o help:
[ -z "$1" ] &amp;&amp; help
[ "$1" = "-h" ] &amp;&amp; help

# Envia a sequ&ecirc;ncia de escape que muda o titulo da barra xtem:
echo -e "\033]0;$1\007"
#
</PRE>
&Eacute; um bom habito de ter sempre uma ajuda extensiva dentro dos scripts.
Isto torna poss&iacute;vel para os outros (e voc&ecirc;) utilizar e perceber o script.<BR> <BR>
<B>Argumentos da linha de comandos</B><BR>
Vimos que S* e $1, $2 ... $9
cont&ecirc;m os argumentos que o utilizador pode especificar na linha de comandos (as
strings escritas a seguir o nome do programa). At&eacute; aqui tivemos uma syntax de
linha de comandos bastante simples ou com poucos argumentos (alguns argumentos
obrigat&oacute;rios e a op&ccedil;&atilde;o -h para ajuda). Mas rapidamente voc&ecirc; ira descobrir que
necessita de um tipo de analisador para programas mais complexos onde voc&ecirc;
define as suas pr&oacute;prias op&ccedil;ões. Por conven&ccedil;&atilde;o todos esses par&acirc;metros opcionais
s&atilde;o precedidos por um sinal - e t&ecirc;m de ser introduzidos antes qualquer outro
argumento (como por exemplo os nome dos ficheiros). <BR> <BR>
Existem varias possibilidades para implementar um analisador. O seguinte ciclo
while combinado com uma instru&ccedil;&atilde;o case &eacute; uma solu&ccedil;&atilde;o muita boa para um analizador
<A href="../../common/src/article216/cmdparser.txt">gen&eacute;rico</A>:
<PRE>
#!/bin/sh
help()
{
  cat &lt;&lt;HELP
Isto &eacute; uma demo de um analisador de comando.
EXEMPLO DE UTILIZA&Ccedil;&Atilde;O: cmdparser -l hello -f -- -ficheiro1 ficheiro2
HELP
  exit 0
}

while [ -n "$1" ]; do
case $1 in
    -h) help;shift 1;; # a fun&ccedil;&atilde;o help &eacute; chamada
    -f) opt_f=1;shift 1;; # a vari&aacute;vel opt_f &eacute; inicializada
    -l) opt_l=$2;shift 2;; # -l pega num argumento -&gt; shift por 2
    --) shift;break;; # fim das op&ccedil;ões
    -*) echo "erro: n&atilde;o exista a op&ccedil;&atilde;o $1. -h para help";exit 1;;
    *)  break;;
esac
done

echo "opt_f &eacute; $opt_f"
echo "opt_l &eacute; $opt_l"
echo "primeiro argumento &eacute; $1"
echo "2nd argumento &eacute; $2"
</PRE>
Experimenta ! POde excuta-lo com por exemplo:
<PRE>
cmdparser -l hello -f -- -umficheiro1 umficheiro2 </PRE>
Ele ira produzir
<PRE>
opt_f &eacute; 1
opt_l &eacute; hello
primeiro argumento &eacute; -umficheiro1
2nd argumento &eacute; umficheiro2 </PRE>
Como &eacute; que ele funciona ?
Basicamente ele faz um loop pelo todos os argumentos e verifica se coincidam
com a instru&ccedil;&atilde;o case. Se ele encontrar algum que coincida ele carrega a
vari&aacute;vel e shift a linha de comando por um.  A conven&ccedil;&atilde;o unix &eacute; que as op&ccedil;ões
(coisas come&ccedil;ando com o menos) t&ecirc;m de vir em primeiro. Voc&ecirc; deve de indicar no
fim da op&ccedil;&atilde;o escrevendo dois sinais menos (--). Voc&ecirc; precisa, com grep por
exemplo, pesquisar uma string que come&ccedil;a com o sinal menos:
<PRE>
Procura de -xx- no ficheiro f.txt:
grep -- -xx- f.txt </PRE>
O nosso option parser pode manipular os -- tamb&eacute;m como pode ver na listagem acima.

<A NAME="216lfindex5">&nbsp;</A>
<H2>Exemplos</H2>
 <B>Um esqueleto para uma utiliza&ccedil;&atilde;o gen&eacute;rica</B><BR> <BR>
Agora j&aacute; falamos sobre praticamente todos os componentes que necessita para
escrever um script. Todos os bons scripts t&ecirc;m de ter uma ajuda e pode tamb&eacute;m
ter uma op&ccedil;&atilde;o por defeito mesmo tendo uma unica op&ccedil;&atilde;o. Por isso &eacute; uma boa ideia
ter um script modelo, chamado <A href=
"../../common/src/article216/framework.sh.txt">framework.sh</A>, o qual voc&ecirc;
pode utilizar como estrutura para outros scripts. Se deseja escrever um novo
script basta fazer uma copia:
<PRE>
cp framework.sh myscript </PRE>
e inserir a actual funcionalidade dentro de "myscript". <BR> <BR>
Vamos agora ver mais dois exemplos: <BR> <BR>
<B>Convers&atilde;o de um numero bin&aacute;rio para decimal</B><BR> <BR>
O script <A href="../../common/src/article216/b2d.txt">b2d</A> converte um
numero bin&aacute;rio (ex: 1101) para o seu equivalente em decimal. &Eacute; um exemplo que
mostra que pode fazer opera&ccedil;ões matem&aacute;ticas simples com expr:
<PRE>
#!/bin/sh
# vim: set sw=4 ts=4 et:
help()
{
 cat &lt;&lt;HELP b2h
-- converte bin&aacute;rio para decimal

UTILIZA&Ccedil;&Atilde;O: b2h [-h] binarynum

OP&Ccedil;&Otilde;ES: -h help text

EXEMPLO: b2h 111010 retorna 58 HELP exit 0 }

error()
{
    # escreve um erro e sai
    echo "$1" exit 1
}

lastchar()
{
    # devolve o ultimo caracter de uma string no $rval
    if [ -z "$1" ]; then
        # string vazia
        rval="" return fi
    # wc coloca algum espa&ccedil;o atras o output &eacute; por caso disso que necessitamos
    # de sed:
    numofchar=`echo -n "$1" | wc -c | sed 's/ //g' `
    # agora corta o ultimo caractero
    rval=`echo -n "$1" | cut -b $numofchar`
}

chop()
{
    # remove o ultimo caracter numa string and retorno dentro de $rval
    if [ -z "$1" ]; then
        # string vazia
        rval="" return fi
    # wc coloca algum espa&ccedil;o atras o output &eacute; por caso disso que necessitamos
    # de sed:
    numofchar=`echo -n "$1" | wc -c | sed 's/ //g' `
    if [ "$numofchar" = "1" ]; then
        # unicamente um caracter na string
        rval=""
        return
    fi
    numofcharminus1=`expr $numofchar "-" 1`
    # agora corta tudo mas o ultimo caractero:
    rval=`echo -n "$1" | cut -b 0-${numofcharminus1}`
}


while [ -n "$1" ]; do
case $1 in
    -h) help;shift 1;; # fun&ccedil;&atilde;o help &eacute; chamada
    --) shift;break;; # fim das op&ccedil;ões
    -*) error "erro: no such option $1. -h for help";;
     *)  break;;
esac
done

# O programa principal
sum=0
weight=1
# T&ecirc;m de ser dado um argumento:
[ -z "$1" ] &amp;&amp; help
binnum="$1"
binnumorig="$1"

while [ -n "$binnum" ]; do
   lastchar "$binnum"
   if [ "$rval" = "1" ]; then
       sum=`expr "$weight" "+" "$sum"`
   fi
   # remove a ultima posi&ccedil;&atilde;o no $binnum
   chop "$binnum"
   binnum="$rval"
   weight=`expr "$weight" "*" 2`
done

echo "bin&aacute;rio $binnumorig &eacute; decimal $sum"
# </PRE>
O algoritmo utilizado neste script pega no peso decimal (1,2,4,8,16,..)
de cada numero come&ccedil;ando com o numero mais a direita e adiciona-o a soma se o
n&uacute;mero &eacute; um 1. Desta maneira "10" &eacute;: <BR>
0 * 1 + 1 * 2 = 2 <BR>
Para obter os
n&uacute;meros da string utilizamos a fun&ccedil;&atilde;o lastchar.  Esta ultima utiliza wc -c para
contar o numero de caracteres da string e vai cortando o &uacute;ltimo caracter. A
fun&ccedil;&atilde;o chop t&ecirc;m a mesma l&oacute;gica mas remove o &uacute;ltimo caracter, isto &eacute; que ele
remove tudo desde o inicio at&eacute; o pen&uacute;ltimo caracter.  <BR> <BR>
<B>Um programa de rota&ccedil;&atilde;o de ficheiros</B><BR>
Provavelmente voc&ecirc; &eacute; um desses que grava todo o
mail que sai para um ficheiro. Depois de algum meses esse ficheiro se torna
bastante grande e torna o acesso lente se voc&ecirc; o l&ecirc; dentro do seu programa de
mail.  O script seguinte <A href=
"../../common/src/article216/rotatefile.txt">rotatefile</A> pode ajudar. Ele
renomeia o mailfolder, vamos chama-lo outmail, para outmail.1 se j&aacute; existir um
ent&atilde;o ele torna-se outmail.2 etc...
<PRE>
#!/bin/sh
# vim: set sw=4 ts=4 et:
ver="0.1"
help()
{
    cat &lt;&lt;HELP
rotatefile -- roda de ficheiro

UTILIZA&Ccedil;&Atilde;O: rotatefile [-h] ficheiro

OP&Ccedil;&Otilde;ES: -h help text

EXEMPLO: rotatefile out Isto ira renomeiar por exemplo out.2 para out.3, out.1
para out.2, out para out.1 e criar um ficheiro out vazio

O numero m&aacute;ximo &eacute; 10

version $ver
HELP
   exit 0
}

error()
{
    echo "$1"
    exit 1
}
while [ -n "$1" ]; do
case $1 in
    -h) help;shift 1;;
    --) break;;
    -*) echo "erro: no such option $1. -h for help";exit 1;;
     *) break;;
esac
done

# verifica&ccedil;&atilde;o de input:
if [ -z "$1" ] ; then
 error "ERRO: t&ecirc;m de especificar um ficheiro, utiliza -h para ajuda"
fi
filen="$1"

# renomeia qualquer ficheiro .1 , .2 etc:
for n in  9 8 7 6 5 4 3 2 1; do
   if [ -f "$filen.$n" ]; then
      p=`expr $n + 1`
      echo "mv $filen.$n $filen.$p"
      mv $filen.$n $filen.$p
   fi
done

# renomeia o ficheiro original:
if [ -f "$filen" ]; then
   echo "mv $filen $filen.1"
   mv $filen $filen.1
fi
echo touch $filen
touch $filen </PRE>
Como funciona o programa ? Ap&oacute;s verifica&ccedil;&atilde;o que o utilizador introduziu
um ficheiro vamos para um ciclo que vai de 9 a 1. O ficheiro 9 &eacute; agora
renomeado para 10, ficheiro 8 para 9 e assim por diante. Depois do ciclo
renomeamos o ficheiro original para 1 e criamos um ficheiro vazio com o nome do
ficheiro original.

<A NAME="216lfindex6">&nbsp;</A>
<H2>Debugging</H2>

A ajuda mais simples para debugging &eacute; obviamente o comando echo.  Voc&ecirc; pode
utiliza-lo para ver o conte&uacute;do de uma vari&aacute;vel especifica perto do sitio onde
voc&ecirc; suspeita estar o erro. &Eacute; provavelmente o que os programadores em shell fazem
80% das vezes para procurar um erro.  A avantajem do shell scripting &eacute; que n&atilde;o &eacute;
necess&aacute;rio recompilar e inserir um comando "echo" &eacute; feito muito rapidamente. <BR> <BR>
O shell tem tamb&eacute;m um verdadeiro modo debug. Se existir um erro no seu script
"strangescript" ent&atilde;o pode fazer debug desta forma:
<PRE>
sh -x strangescript </PRE>
Isto ira executar o script e mostrar todos as instru&ccedil;ões que s&atilde;o executadas com as
vari&aacute;veis e wildcards j&aacute; expandido. <BR> <BR>
O shell t&ecirc;m tamb&eacute;m um modo para verificar a sintaxe sem realmente executar o programa.
Para utilizar fazer:
<PRE>
sh -n o_script </PRE>
Se n&atilde;o retornar nada ent&atilde;o o seu programa esta sem erros de sintaxe.  <BR> <BR>
Esperamos que agora ira come&ccedil;ar a escrever os seus pr&oacute;prios scripts.  Divirta-se !<BR>

<A NAME="216lfindex7">&nbsp;</A>
<H2>Refer&ecirc;ncias</H2>


    <UL> <LI>A pagina man e pagina info do pash s&atilde;o muita boas e ira descobrir
mais truques aqui:<BR> man bash<BR> tkinfo bash<BR> (Eu detesto o browser
standard mas  <A href=
"http://math-www.uni-paderborn.de/~axel/tkinfo/">tkinfo</A> ou konqueror (o url
&eacute; info:/bash/Top ) s&atilde;o bastante bons)</LI>

      <LI>O artigo na LinuxFocus em <A href=
"../November2000/article131.shtml">GNU file utilities</A></LI>

      <LI>O artigo na LinuxFocus em <A href=
"../July1998/article53.html">Regular expressions</A></LI>

      <LI>O artigo na LinuxFocus em <A href=
"../September1999/article103.html">AWK</A></LI>

      <LI>O artigo na LinuxFocus em <A href=
"../November1998/article68.html">Basic UNIX commands</A></LI>

      <LI>Se bash ainda n&atilde;o esta instalado no seu sistema ou quer obter a
ultima vers&atilde;o voc&ecirc; pode fazer download do site GNU em http://www.gnu.org (para
descobrir se o bash j&aacute; esta instalado no seu sistema basta escrever bash. Se
n&atilde;o tiver nenhuma mensagem de erro ent&atilde;o o bash j&aacute; esta instalado)</LI> </UL>
<!-- vim: set sw=2 ts=2 et: -->  


<!-- 2pdaIgnoreStart -->
<A NAME="talkback">&nbsp;</a>
<h2>Forma de respostas para este artigo</h2>
Todo artigo tem sua pr&oacute;pria p&aacute;gina de respostas. Nesta p&aacute;gina voc&ecirc; pode enviar um coment&aacute;rio ou ver os coment&aacute;rios de outros leitores:
<center>
<table border="0"  CELLSPACING="2" CELLPADDING="1">
 <tr BGCOLOR="#C2C2C2"><td align=center>
  <table border="3"  CELLSPACING="2" CELLPADDING="1">
   <tr BGCOLOR="#C2C2C2"><td align=center>
    <A href="http://cgi.linuxfocus.org/cgi-bin/lftalkback?anum=216&amp;lang=pt"><b>&nbsp;p&aacute;gina de respostas&nbsp;</b></a>
   </td></tr></table>
</td></tr></table>
</center>

<HR size="2" noshade>
<!-- ARTICLE FOOT -->
<CENTER><TABLE WIDTH="98%">
<TR><TD ALIGN=CENTER BGCOLOR="#9999AA" WIDTH="50%">
<A HREF="../../common/lfteam.html">P&aacute;ginas Web mantidas pelo time de Editores LinuxFocus</A>
<BR><FONT COLOR="#FFFFFF">&copy; Katja and Guido Socher, <a href="../../common/copy.html">FDL</a> <BR><a href="http://www.linuxfocus.org">LinuxFocus.org</a></FONT>
<BR><a href="http://cgi.linuxfocus.org/cgi-bin/lfcomment?lang=pt&amp;article=article216.shtml" target="_TOP">Clique aqui para reportar uma falha ou para enviar um coment&aacute;rio para LinuxFocus</A><BR></TD>
<TD BGCOLOR="#9999AA">
<!-- TRANSLATION INFO -->
<font size=2>Informa&ccedil;&atilde;o sobre tradu&ccedil;&atilde;o:</font>
<TABLE>
  <tr><td><font size="2">en --&gt; -- : Katja and Guido Socher <small>&lt;katja(at)linuxfocusorg, guido(at)linuxfocus.org&gt;</small></font></td></tr>
  <tr><td><font size="2">en --&gt; pt: Patrick Carpalhoso  &lt;carpalhoso(at)mail.telepac.pt&gt;</font></td></tr>
</TABLE>
</TD>
</TR></TABLE></CENTER>
<p><font size=1>2002-04-23, generated by lfparser version 2.27</font></p>
<!-- 2pdaIgnoreStop -->
</BODY>
</HTML>