original in en Katja and Guido Socher
en to pt Patrick Carpalhoso
Katja � a editora germ�nica de LinuxFocus. Ela gosta de Tux, filmes & fotografia e o mar. A sua p�gina pessoal encontra-se aqui.
Guido � um fan de Linux desde a muito e gosta do Linux porque ele foi criado por pessoas honestas e de mentalidade aberta. � uma das raz�es porque o chamamos open source. A sua p�gina pessoal esta no linuxfocus.org/~guido.
#!/bin/shOs caracteres #! informam o sistema que o primeiro argumento que segue na linha � o programa utilizado para executar este ficheiro. Neste caso /bin/sh � o shell que utilizamos.
vari�vel=valorPara ler o conte�do de uma vari�vel basta colocar um cifr�o antes da vari�vel;
#!/bin/sh # atribui um valor: a="hello world" # e agora escreve o conte�do de "a": echo "A �:" echo $aEscreva estas linhas no seu editor de texto e grave com o nome first. Ponha o script execut�vel escrevendo chmod +x first no shell e executa escrevendo ./first
A �: hello worldPor vezes � poss�vel confundir os nomes das vari�veis com o resto do texto:
num=2 echo "isto � o $numnd"Isto n�o vai imprimir "isto � 2nd" mas "isto � " porque o shell vai procurar por uma vari�vel chamada numnd que n�o tem valor nenhum. Para dizer ao shell que estamos a fazer refer�ncia a vari�vel num temos que usar as chavetas:
num=2 echo "isto � o ${num}nd"Desta forma vai escrever: isto � o 2nd
Syntax de comandos | Objectivo |
---|---|
echo "algum texto" | escreve algum texto no ecr� |
ls | lista ficheiros |
wc -l ficheiro wc -w ficheiro wc -c ficheiro |
conta as linhas num ficheiro ou conta o numero de palavras conta os numeros caracteres |
cp ficheiroorigem ficheirodestino | copia ficheiroorigem para ficheirodestino |
mv nomeantigo novonome | renomeia ou move um ficheiro |
rm ficheiro | apaga um ficheiro |
grep 'qualquercoisa' ficheiro | procura por strings num ficheiro Exemplo: grep 'qualquercoisa' ficheiro.txt |
cut -b colnum file | extrai dados de uma coluna fixa de texto Exemplo: extrai caracteres da posi��o 5 a 9 cut -b5-9 file.txt N�o confundir com o comando "cat" que faz uma coisa completamente diferente |
cat ficheiro.txt | escreve o conte�do de ficheiro.txt no stdout (seu ecr�) |
file ficheiroqualquer | descreve qual � o tipo do ficheiro ficheiroqualquer |
read var | pede ao utilizador para escrever e coloca numa vari�vel (var) |
sort ficheiro.txt | ordena as linhas no ficheiro.txt |
uniq | remove as linhas duplicadas, utilizado em combina��o com sort visto
uniq remover unicamente linhas duplicadas consecutivas Exemplo: sort ficheiro.txt | uniq |
expr | faz matem�tica no shell Exemplo: adiciona 2 e 3 expr 2 "+" 3 |
find | procura ficheiros Exemplo: procura por nome: find . -name ficheiro -print Este comando tem muitas possibilidades e op��es. � demasiado para ser explicado ao pormenor neste artigo. |
tee | escreve os dados para stdout (seu ecr�) e para um ficheiro Normalmente utilizado da seguinte forma: umcomando | tee ficheiroout Ele escreve o output de umcomando para o ecr� e para o ficheiro ficheiroout |
basename ficheiro | devolve o nome do ficheiro de um determinado ficheiro e remove o
caminho Exemplo: basename /bin/tux devolve unicamente tux |
dirname ficheiro | devolve unicamente o nome da directoria de um determinado nome e
remove o nome do ficheiro Exemplo: dirname /bin/tux devolve unicamente /bin |
head ficheiro | escreve umas linhas desde o inicio do ficheiro |
tail file | escreve umas linhas desde o fim do ficheiro |
sed | sed � basicamente um programa de pesquisa e substitui��o. Ele l�
texto de um input standard (ex desde um pipe) e escreve o resultado para stdout
(normalmente o ecr�). O padr�o de pesquisa � uma express�o regular (ver
refer�ncias). Esse padr�o de pesquisa n�o deve ser confundido com a syntax da
wildcard do shell. Para substituir a string linuxfocus por LinuxFocus num
ficheiro texto fa�a: cat ficheiro.txt | sed 's/linuxfocus/LinuxFocus/' > novoficheiro.txt Isto substitui a primeira ocur�ncia da string linuxfocus em cada linha com LinuxFocus. Se existirem linhas onde linuxfocus apare�a varias vezes e que queira substituir todos fa�a: cat ficheiro.txt | sed 's/linuxfocus/LinuxFocus/g' > novoficheiro.txt |
awk | A maior parte das vezes awk � utilizado para extrair campos de uma
linha de texto. O separador por defeito � espa�o. Para definir um outro utiliza
a op��o -F. cat ficheiro.txt | awk -F, '{print $1 "," $3 }'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: Adam Bor, 34, India Kerry Miller, 22, USAira dar como resultado: Adam Bor, India Kerry Miller, USAO awk permite fazer muita mais coisas mas esta � a utiliza��o mais frequente. |
grep "hello" ficheiro.txt | wc -lprocura as linhas com a string hello no ficheiro.txt e conta as linhas.
find . -mtime -1 -type f -printprocura todos os ficheiros que foram modificados nas ultimas 24 horas (-mtime -2 significaria 48 horas). Se voc� quer armazenar esse ficheiros num arquivo tar (ficheiro.tar) a syntax para o tar teria de ser:
tar xvf ficheiro.tar ficheiro1 ficheiro2 ...Em vez de escrever isso tudo, voc� pode combinar 2 comandos (find e tar) utilizando backticks. Tar ira aquivar todos os ficheiro que find escreveu:
#!/bin/sh # Backticks (`) n�o plicas ('): tar -zcvf ultimamod.tar.gz `find . -mtime -1 -type f -print`
if ....; then .... elif ....; then .... else .... fiA maior parte das vezes um comando especial chamado test � utilizado dentro de uma instru��o if. Ele pode ser utilizado para comparar strings ou testar se um ficheiro existe, se ele pode ser lido etc...
[ -f "umficheiro" ] : Testa se umficheiro � um ficheiro. [ -x "/bin/ls" ] : Testa se /bin/ls exista e se � um execut�vel. [ -n "$var" ] : Testa se a the vari�vel $var tem algo. [ "$a" = "$b" ] : Testa se as vari�veis "$a" e "$b" s�o iguaisExecuta o comando "man test" para obter uma longa lista de todos os tipos de operadores de teste para compara��es e ficheiros.
#!/bin/sh if [ "$SHELL" = "/bin/bash" ]; then echo "o seu shell de login � o bash (bourne again shell)" else echo "o seu shell de login n�o � bash mas sim $SHELL" fiA vari�vel $SHELL cont�m o nome do shell de login e ela � testada que � comparada com a string "/bin/bash"
[ -f "/etc/shadow" ] && echo "Este computador utiliza shadow passwords"Os && podem ser utilizados como uma curta instru��o if. A parte direita � executada se a parte esquerda for verdadeira. Pode ler isso como AND. Desta maneira o exemplo �: "O ficheiro /etc/shadow exista AND o comando � executada". O operador OR (||) esta tamb�m dispon�vel. Segue um exemplo:
#!/bin/sh mailfolder=/var/spool/mail/james [ -r "$mailfolder" ] || { echo "N�o pode ler $mailfolder" ; exit 1; } echo "$mailfolder t�m um mail de:" grep "^From " $mailfolderO script testa em primeiro se ele pode ler o mailfolder. Se for o caso ele escreve a linha "t�m um mail" no folder, Se ele n�o conseguir ler o ficheiro $mailfolder ent�o o operador OR entra em ac��o. Em Ingl�s voc� pode ler "Mailfolder readable or exit program". O problema aqui � que t�m de ter exactamente um comando atras do OR mas precisamos de 2:
case ... in ...) faz qualquer coisa aqui;; esacVejamos um exemplo. O comando file pode testar qual � o tipo de um ficheiro:
file lf.gz devolve: lf.gz: gzip compressed data, deflated, original filename, last modified: Mon Aug 27 23:09:18 2001, os: UnixVamos utilizar isto agora para escrever um script chamado smartzip que pode descomprimir bzip2, gzip and zip ficheiros comprimidos automaticamente:
#!/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
select var in ... ; do break done .... agora $var pode ser utilizado ....Vejamos este exemplo:
#!/bin/sh echo "Qual � o seu SO preferido ?" select var in "Linux" "Gnu Hurd" "Free BSD" "Other"; do break done echo "Voc� seleccionou $var"O que script faz:
Qual � o seu SO preferido ? 1) Linux 2) Gnu Hurd 3) Free BSD 4) Other #? 1 Voc� seleccionou LinuxNo shell voc� t�m as seguintes instru��es de ciclos dispon�veis:
while ...; do .... doneO ciclo-while sera executada at� que a express�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��o e ignora o resto do corpo do ciclo.
for var in ....; do .... doneO que sega ira imprimir as letras de A a C no ecr�:
#!/bin/sh for var in A B C ; do echo "var � $var" doneUm outro exemplo de script util, chamado showrpm, print uma lista do conte�do de um pacote RPM:
#!/bin/sh # lista um resumo do conte�do de um pacote RPM UTILIZA��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�o consegue ler o ficheiro file $rpmpackage" fi doneComo pode ver a vari�vel especial, $* que cont�m todos os argumentos da linha de comando. Se voc� executar
#!/bin/sh echo *.jpgIsto ira escrever "mail.jpg tux.jpg".
#!/bin/sh echo "*.jpg" echo '*.jpg'Isto ira escrever "*.jpg" 2 vezes.
#!/bin/sh echo $SHELL echo "$SHELL" echo '$SHELL'Isto ira escrever:
/bin/bash /bin/bash $SHELLE por fim exista a possibilidade de aceitar significado especial de qualquer caracter fazendo preceder da backslash:
echo \*.jpg echo \$SHELLIsto ira escrever:
*.jpg $SHELLAqui documentos
#!/bin/sh # Temos menos de 3 argumentos. Escreve o texto do help: if [ $# -lt 3 ] ; then cat <<HELP ren -- renomeia um numero de ficheiros utilizando express�es do sed UTILIZA��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� existe" else echo "renomeando $file para $newfile ..." mv "$file" "$newfile" fi fi done� o script mais complexo que vimos at� aqui. Vamos falar um pouco sobre ele. A primeira instru��o if testa se temos ao menos 3 par�metros na linha de comandos. (A vari�vel especial $# cont�m o numero de argumentos). Se n�o for o caso, o texto do help � enviado ao comando cat que por sua vez mande-o para o ecr�. Depois de escrever o texto do help sa�mos do programa. Se tivermos 3 ou mais argumentos vamos atribuir o primeiro argumento a vari�vel OLD e o segundo a vari�vel NEW. A seguir deslocamos os par�metros da linha de comandos 2 vezes para colocar o terceiro argumento na primeira posi��o de $*. Com $* entramos no ciclo for. Cada um dos argumentos em $* � atribu�do um a um a vari�vel $file. A� vamos em primeiro testar se o ficheiro existe realmente e vamos construir um novo nome de ficheiro utilizando find e sed. Os backticks s�o utilizados para atribuir o resultado para a vari�vel newfile. Agora temos tudo o precisamos: O antigo e novo nome do ficheiro. � o que utilizamos com o comando mv para renomear os ficheiros.
nomedafuncao() { # Dentro do corpo $1 esta o primeiro argumento dado a fun��o No $2 esta o # segundo ... corpo }Tem de "declarar" as fun��es no inicio do script antes de poder utiliza-las.
#!/bin/sh # vim: set sw=4 ts=4 et: help() { cat <<HELP xtitlebar -- muda o nome de um xterm, gnome-terminal ou kde konsole UTILIZA��O: xtitlebar [-h] "texto_para_a_janela" OP��ES: -h help text EXEMPLO: xtitlebar "cvs" HELP exit 0 } # Se ocorrer algum erro ou se for introduzido -h chamamos a fun��o help: [ -z "$1" ] && help [ "$1" = "-h" ] && help # Envia a sequ�ncia de escape que muda o titulo da barra xtem: echo -e "\033]0;$1\007" #� um bom habito de ter sempre uma ajuda extensiva dentro dos scripts. Isto torna poss�vel para os outros (e voc�) utilizar e perceber o script.
#!/bin/sh help() { cat <<HELP Isto � uma demo de um analisador de comando. EXEMPLO DE UTILIZA��O: cmdparser -l hello -f -- -ficheiro1 ficheiro2 HELP exit 0 } while [ -n "$1" ]; do case $1 in -h) help;shift 1;; # a fun��o help � chamada -f) opt_f=1;shift 1;; # a vari�vel opt_f � inicializada -l) opt_l=$2;shift 2;; # -l pega num argumento -> shift por 2 --) shift;break;; # fim das op��es -*) echo "erro: n�o exista a op��o $1. -h para help";exit 1;; *) break;; esac done echo "opt_f � $opt_f" echo "opt_l � $opt_l" echo "primeiro argumento � $1" echo "2nd argumento � $2"Experimenta ! POde excuta-lo com por exemplo:
cmdparser -l hello -f -- -umficheiro1 umficheiro2Ele ira produzir
opt_f � 1 opt_l � hello primeiro argumento � -umficheiro1 2nd argumento � umficheiro2Como � que ele funciona ? Basicamente ele faz um loop pelo todos os argumentos e verifica se coincidam com a instru��o case. Se ele encontrar algum que coincida ele carrega a vari�vel e shift a linha de comando por um. A conven��o unix � que as op��es (coisas come�ando com o menos) t�m de vir em primeiro. Voc� deve de indicar no fim da op��o escrevendo dois sinais menos (--). Voc� precisa, com grep por exemplo, pesquisar uma string que come�a com o sinal menos:
Procura de -xx- no ficheiro f.txt: grep -- -xx- f.txtO nosso option parser pode manipular os -- tamb�m como pode ver na listagem acima.
cp framework.sh myscripte inserir a actual funcionalidade dentro de "myscript".
#!/bin/sh # vim: set sw=4 ts=4 et: help() { cat <<HELP b2h -- converte bin�rio para decimal UTILIZA��O: b2h [-h] binarynum OP��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�o atras o output � 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�o atras o output � 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��o help � chamada --) shift;break;; # fim das op��es -*) error "erro: no such option $1. -h for help";; *) break;; esac done # O programa principal sum=0 weight=1 # T�m de ser dado um argumento: [ -z "$1" ] && help binnum="$1" binnumorig="$1" while [ -n "$binnum" ]; do lastchar "$binnum" if [ "$rval" = "1" ]; then sum=`expr "$weight" "+" "$sum"` fi # remove a ultima posi��o no $binnum chop "$binnum" binnum="$rval" weight=`expr "$weight" "*" 2` done echo "bin�rio $binnumorig � decimal $sum" #O algoritmo utilizado neste script pega no peso decimal (1,2,4,8,16,..) de cada numero come�ando com o numero mais a direita e adiciona-o a soma se o n�mero � um 1. Desta maneira "10" �:
#!/bin/sh # vim: set sw=4 ts=4 et: ver="0.1" help() { cat <<HELP rotatefile -- roda de ficheiro UTILIZA��O: rotatefile [-h] ficheiro OP��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�ximo � 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��o de input: if [ -z "$1" ] ; then error "ERRO: t�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 $filenComo funciona o programa ? Ap�s verifica��o que o utilizador introduziu um ficheiro vamos para um ciclo que vai de 9 a 1. O ficheiro 9 � 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.
sh -x strangescriptIsto ira executar o script e mostrar todos as instru��es que s�o executadas com as vari�veis e wildcards j� expandido.
sh -n o_scriptSe n�o retornar nada ent�o o seu programa esta sem erros de sintaxe.