Capítulo 08: Coisas úteis de se aprender ←

Exemplos Variados

Aqui pretendo listar alguns scripts que possuem uma ou mais das seguintes características: é útil, é bem escrito, é didático.

Eu poderia ficar "enchendo linguiça" metendo vários exemplos, mas o objetivo é apenas ilustrar que vários conceitos mostrados no livro podem ser utilizados em conjunto num mesmo script. Se você quer mais exemplos olhe as Referências.

backup.sh

#!/bin/bash
# backup.sh
#
# OBS.: Por favor melhore este script! :-)

# Se o número de parâmetros for menor que 2...
[ $# -lt 2 ] && {
  echo "Uso: `basename $0` destino origem [origem2 origem3...]"
  exit 1        # ... sai do script
}

echo "--> Fazendo backup"
FILE="${1}_$(/bin/date +%d-%m-%Y).tgz"
shift
# Aqui está o "segredo": o shift acima é executado para que eu possa
# usar "$*" no if abaixo.

if tar czf $FILE $* ; then
  echo "--> Backup feito com sucesso"
else
  echo "--> OCORREU UM ERRO &2
  exit 1
fi

howto.sh

#!/bin/bash
# howto.sh
#
# *********************************************
# * Script para visualizar HOWTOs rapidamente *
# *********************************************
#               http://meleu.da.ru
#          meleu 
#
#    Inspirado em um outro script que vi no Tips-HOWTO.
#    O script do Tips-HOWTO era muito simples, fiz algumas
# modificações que são interessantes para nós que falamos
# português e de vez em quando temos uns HOWTOs traduzidos,
# e ainda fiz um "suporte" aos mini-HOWTOs. ;-)
#    E mais: se você não lembra direito do nome do HOWTO, pode
# passar apenas a(s) primeira(s) letra(s) e/ou usar os curingas
# ('*', '?' e '[]'), mas aconselha-se, neste último caso, o uso de
# aspas ("quoting") para evitar que seja passado como parâmetro(s)
# o conteúdo do diretório atual. Caso ele encontre mais de um
# arquivo para a expressão você poderá escolher através da tela que
# aparecerá.
# Exemplos:
# [prompt]$ howto Net
# [prompt]$ howto "*[Bb]ash"
# [prompt]$ howto "*Prog"
#
#    Se você ainda não tem e não sabe onde pegar HOWTOs traduzidos
# procure em http://ldp-br.conectiva.com.br
#
# Pré-requisitos para o script funcionar direitinho (ou seja, sem
# precisar de alterações):
#    + os HOWTOs devem estar em "/usr/doc/Linux-HOWTOs";
#    + os HOWTOs em português devem estar em "/usr/doc/Linux-HOWTOs.pt";
#    + os mini-HOWTOs devem estar em "/usr/doc/Linux-mini-HOWTOs";
#    + todos os [mini-]HOWTOs[.pt] devem estar gzipados, se os seus não
#      estão assim basta entrar no diretório dos HOWTOs e digitar
#      "gzip *".
#
#
#    Se você testou o script, ele funcionou direitinho e você gostou,
# então digite "cp howto.sh /usr/local/bin/howto" para que todos do
# seu sistema possam utilizá-lo. ;-)
#
# Aproveite!


# Estes são os diretórios onde são instalados os [mini-]HOWTOs no
# Slackware. Se a sua distribuição usa um diretório diferente
# mude a(s) variável(is) a seguir.
HTDIR=/usr/doc/Linux-HOWTOs
miniHTDIR=/usr/doc/Linux-mini-HOWTOs
PTHTDIR=/usr/doc/Linux-HOWTOs.pt     # este é onde eu coloco os traduzidos


# Variáveis que indicam as cores (pra não precisar ficar
# digitando os códigos ANSI toda hora)
BLUE="\e[1;34m"
RED="\e[1;31m"
NCOLOR="\e[m"


function Ler {
zless $1
echo -e "${RED}\nTchau!\n$NCOLOR"
exit
}

# Função que mostra a lista dos HOWTOs e sai do script.
function Lista {
        ls -C $HTDIR | less
        echo -e "
${BLUE}Uso:$NCOLOR `basename $0` [-p | -m] nome-do-HOWTO
Faça '`basename $0` -h' para ver a descrição das opções."
	exit 1
}


# se não for passado nenhum parâmetro ele mostra a lista
[ -z "$1" ] && Lista


# --------------------
# - TESTA PARÂMETROS -
# --------------------
case $1 in

#  - mensagem de ajuda -
#  ---------------------
-h) echo -e "
${RED}--[ Lista de opções ]--$NCOLOR
-p \t HOWTOs em português
-m \t mini-HOWTOs
-h \t imprime esta mensagem
"
    exit	# depois da mensagem de ajuda, sair
;;

# - HOWTOs em português -
# -----------------------
-p) HTDIR=$PTHTDIR
    [ -z "$2" ] && Lista
    shift	# Lembra do 'shift'? Aqui ele faz com que o primeiro
		# parâmetro deixe de ser '-p' para ser o nome-do-HOWTO
;;

# - mini-HOWTOs -
# ---------------
-m) HTDIR=$miniHTDIR
    [ -z "$2" ] && Lista
    shift	# mesma função do shift no '-p'
;;

esac	# Ao fim deste case $1 tem necessariamente o nome ou a(s)
	# primeira(s) letra(s) do nome do HOWTO a ser procurado.

cd $HTDIR

FILE=`ls $1*.gz 2>/dev/null`

[ `echo $FILE | wc -w` -gt 1 ] && {
   PS3="Entre com o número: "
   select opc in $FILE Sair ; do

	[ "$opc" = "Sair" ] && exit

	for HOWTO in $FILE ; do
	    [ "$opc" = "$HOWTO" ] && Ler $HOWTO
	done
    done
}

[ -e "$FILE" ] && Ler $FILE


# Isto só será executado se não for encontrado o HOWTO
echo -e "${RED}* * * HOWTO não encontrado * * *$NCOLOR"
echo "Tente '`basename $0` [-p | -m]' para ver a lista"
exit 1

# - = < E O F > = -

todo.sh

#!/bin/bash
# todo.sh

PROG=`basename $0`
EDITOR=`which vi`
FILE="$HOME/.ToDo"
USAGE="Uso: $PROG [-h|-e]"

case $1 in
        -h) echo "
$USAGE

-e	edita a lista de \"Para Fazer\" (To Do)
-h	imprime esta mensagem e sai

Sem parâmetros $PROG irá mostrar a lista de \"To-Do\".
"
	    exit ;;

	-e) $EDITOR $FILE
	    exit ;;

	'') cat $FILE 2> /dev/null || {
		echo "Você precisa criar o arquivo $HOME/.ToDo !"
		echo "Entre \"$PROG -e\" para editar seu ~/.ToDo"
		echo "Para ajuda tente \"$PROG -h\""
		exit 1
	    } ;;

	*) echo "Parâmetro \"$1\" desconhecido!"
	   echo "$USAGE"
	   echo "Entre com \"$PROG -h\" para ajuda."
	   exit ;;

esac

inseretxt.sh

#!/bin/bash
# inseretxt.sh
#
# Muitas vezes durante a escrita do texto
# "Programação em Bourne-Again Shell" eu precisava
# inserir um código de um script numa determinada
# posição do arquivo e esta posição ficava entre
# muito texto antes e depois dessa linha.
# Para fazer isso de uma maneira mais cômoda, eu
# escrevi este script.
#
# Para informações sobre o uso tente o parâmetro '-h' ou
# '--help'.
# Se você passar como o parâmetro "linha" um número maior
# que o de linhas total do "ArqOriginal" os "arquivosN"
# serão inseridos no final do "ArqOriginal".
#
# Ah! Lembre-se de uma coisa: "linha" precisa ser um
# inteiro positivo. E lembre-se de mais uma coisa: 0
# não é um número positivo. ;-)
#
# meleu.
#


B="\e[1m"
N="\e[m"
USO="Uso: `basename $0` linha ArqOriginal arquivo1 [arquivoN ...]"
AJUDA="Tente \"`basename $0` --help\" para ajuda"

[ "$1" = '-h' -o "$1" = '--help' ] && {
    echo -e "
${B}Insere o conteúdo de arquivo(s) dentro de um outro.$N

$USO

Onde:
\"linha\"       é a linha onde o texto será inserido
\"ArqOriginal\" é o arquivo que receberá os textos 
\"arquivoN\"    são os arquivos que serão inseridos em ArqOriginal
"
    exit
}

[ $# -lt 3 ] && {
    echo -e ${B}Erro: erro na passagem de parâmetros$N
    echo $USO
    echo $AJUDA
    exit -1
}

Linha=$1
# verificando se $Linha é um número inteiro positivo
[ `expr $Linha - 1 2>/dev/null` -ge 0 ] 2>/dev/null || {
    echo -e ${B}Erro: O primeiro parâmetro precisa ser inteiro positivo$N
    echo $AJUDA
    exit 1
}

ArqOriginal=$2
[ -f $ArqOriginal ] || {
    echo -e ${B}Erro: \"$ArqOriginal\" não existe ou não é um arquivo regular$N
    echo $AJUDA
    exit 2
}


function ApagarSair {
    rm "$1"
    exit $2
}


shift 2
Temp=/tmp/`basename $ArqOriginal`-$$.tmp

# --> início do arquivo original:
head -$[$Linha-1] $ArqOriginal > $Temp

# --> arquivos que serão inseridos:
ContaAcerto=0
for Arq in "$@"; do
    [ -f "$Arq" ] || {
	echo -e ${B}OBS.: \"$Arq\" não existe ou não é um arquivo regular$N
	continue
    }
    cat $Arq >> $Temp
    (( ContaAcerto++ ))
done
[ $ContaAcerto -eq 0 ] && {
    echo -e ${B}Nenhum arquivo foi inserido em \"$ArqOriginal\"$N
    ApagarSair $Temp 3
}
echo

# --> pra terminar, final do arquivo original:
sed -n "$Linha,\$p" $ArqOriginal >> $Temp


ArqFinal="$ArqOriginal.new"
[ -e $ArqFinal ] && {
    echo -e ${B}Já existe um arquivo chamado \"$ArqFinal\".$N
    read -n 1 -p "Deseja sobregravá-lo? (s/N) " SN
    echo
    [ "$SN" != 'S' -a "$SN" != 's' ] && {
	echo -e "$B\nOperação cancelada!$N"
	ApagarSair $Temp 3
    }
}

cat $Temp > $ArqFinal

echo -e "
${B}Operação concluída com sucesso.$N
Confira em \"$ArqFinal\"
"

ApagarSair $Temp

Mextract.sh

#!/bin/sh
# Mextract.sh
#
# ****************************
# * Meleu Extraction Utility *
# ****************************
#      http://meleu.da.ru
#
#   Este script é baseado no Phrack Extraction Utility, (mais informações
# ). Fiz ele, primeiro para praticar, segundo para
# servir como mais um exemplo no texto "Programação em Bourne-Again Shell", 
# e último para extração dos códigos do texto. =P
#
############# Se já existirem arquivos com o nome dos que serão extraídos
# !CUIDADO! # eles serão sobregravados! Portanto, se você extrair uma vez,
############# alterar o(s) código(s) extraído(s) e extrair novamente,
#             perderá as alterações feitas!
#
#
#   A seguir eu vou comentar sobre o código fazendo referência aos tópicos
# do texto "Programação em Bourne-Again Shell".
#
#
#    + A função do IFS é explicada no tópico "2.2. Variáveis do Shell",
# neste script eu usei o IFS com valor nulo (vazio) para que os comandos
# considerem espaços que vêm antes de qualquer caractere como parte do
# dado. Se você fizer por exemplo "read var" e antes de entrar qualquer
# coisa colocar espaços e/ou TAB, você verá que eles serão desconsiderados
# se o IFS tiver seu valor default (espaço, TAB, newline);
#
#    + A opção -r no read (explicada em 3.2. read) serve para ignorar o
# poder que a contra-barra (backslash) tem de "escapar" os caracteres. Em
# outras palavras: a opção -r garante que quando o read receber uma
# contra-barra ela será passada para a variável sem nenhum valor especial;
#
#    + O cat enviando os dados para o read do while é explicado em
# "5.5. Redirecionando loops" sob o título de "pipeando para o while";
#
#    + o set é usado para fazer com que cada palavra (palavra aqui tem um
# sentido de conjunto de caracteres separados por aqueles definidos no
# IFS) vire um parâmetro posicional, conforme explicado em
# "2.4.2. set (para editar parâmetros posicionais)". A opção -- quer dizer
# "acabaram as opções, o que vier a partir daqui são os valores dos
# parâmetros de posição", esta opção serve para prevenir que alguma
# informação que comece com o caractere - seja considerado uma opção
# sendo passada para o set;
#
#    + No tópico "2.5. Substituição de Variáveis" você verá a explicação
# de se usar "FILE=${FILE:-.}/$1";
#
#    + Bom... acho que é isso. Leia o código, execute-o, faça testes,
# mude o código, execute-o novamente, veja o que mudou nos resultados,
# leia as manpages em caso de dúvidas... Enfim, use o método hacker de
# aprender a programar! ;-)
#
#
# Espero que curta!
# meleu 
#
# P.S.: Quer um "dever de casa"? Altere o código para que ele verifique
#	se já existe arquivos com o mesmo nome dos que estão prestes a
#	serem extraídos. Se existir, alertar o usuário sobre isso. Tente
#	também fazer meios de detecção dos possíveis erros que possam
#	ocorrer...
#	Ah, sei lá! Brinque com o código um pouco! =)
#

B="\e[1m"
N="\e[m"

[ $# -lt 1 ] && {
    echo -e "${B}Erro: falta parâmetros$N"
    echo "Uso: `basename $0` arquivo1 [arquivoN]"
    exit 1
}

[ -w . ] || {
    echo -e "${B}Erro: você não tem permissão de escrita neste diretório$N"
    exit 1
}


OldIFS="$IFS"
IFS=
cat $@ |
while read -r LINHA ; do
	IFS="$OldIFS"

	set -- $LINHA
	case "$1" in
	'')
		TempIFS="$IFS"
		IFS=/
		set -- $2
		IFS="$TempIFS"
		while [ $# -gt 1 ]; do
		    FILE=${FILE:-.}/$1
		    [ -d $FILE ] || mkdir $FILE
		    shift
		done
		FILE="${FILE:-.}/$1"
		if echo -n 2>/dev/null > $FILE ; then
		    echo "* Extraindo $FILE"
		else
		    echo -e "$B--> houve um erro ao tentar extrair '$FILE'"
		    echo -e "    este arquivo será ignorado.$N"
		    unset FILE
		fi
		
	;;

	'')
		unset FILE
	;;

	*)
		[ "$FILE" ] && {
		    IFS=
		    echo "$LINHA" >> $FILE
		}
	;;

	esac

done

echo "--> Fim 

Capítulo 10: Referências →

results matching ""

    No results matching ""