Funções como comandos
Antes de começar vamos relembrar um conceito básico: quando se executa um shell script você obtém o mesmo resultado que obteria se digitasse o conteúdo do script no prompt de um shell. Com isso eu quero dizer que você pode fazer tudo que faz em um shell script na linha de comando, inclusive criar e utilizar funções (que é o assunto deste tópico).
Bom chega de falar de coisas óbvias... :-)
Na linha de comando você declara uma função da mesma maneira que faz num script. Por exemplo, digite o seguinte na sua linha de comando:
function heko {
echo -e "\e[5;1;32mHekodangews, para de enrolar a mina e casa logo! \e[m"
}
Agora quando você entrar com "heko" na linha de comando será impresso na tela um recadinho para o Hekodangews numa corzinha verde e piscante super-fashion. =)
Veja este outro exemplo um pouco mais útil:
function SetPath {
PATH=${PATH:="/bin:/usr/bin"}
for DIR in "$@"; do
if [ -d "$DIR" ]; then
PATH="$PATH:$DIR"
else
echo "* * * Erro: $DIR nao eh um diretorio"
fi
done
export PATH
unset DIR
}
Acho que deu pra sacar qual é, né? Quando você quiser acrescentar algum
diretório no seu PATH
basta usar SetPath dir1 dir2 dirn
. ;-)
E se você tiver várias idéias de funções legais que queira usar sempre
em suas sessões? Vai ter que digitá-las na linha de comando toda hora?
Não! Para este propósito o comando source
pode ser muito útil
(informações detalhadas na manpage do bash).
Lembra-se de eu ficar enchendo o saco dizendo "Quando executamos um shellscript ele é executado num shell a parte (shell filho)"? Pois eu não fiquei enchendo o saco com isso sem motivo. O comando source faz com que o script seja executado no shell pai, ou seja, é como você estivesse digitando todo o conteúdo do arquivo na linha de comando. E isso é especialmente útil quando temos arquivos com as nossas funções que queremos usar como comandos.
Uma coisa legal de se fazer é colocar o arquivo com as funções que
você quer usar num arquivo oculto no seu $HOME
(ex.: $HOME/.MyFunctions
)
e no seu $HOME/.bash_profile
você coloca uma linha com o comando
source $HOME/.MyFunctions
.
Veja este arquivo com alguns exemplos de funções:
#!/bin/bash
# Mfunctions
#
# "INSTALAÇÃO":
# copie este arquivo para seu $HOME:
# [prompt]$ cp Mfunctions ~/.Mfunctions
#
# depois faça o seguinte:
# [prompt]$ echo ". ~/.Mfunctions" >> ~/.bash_profile
#
# Dê login novamente ou digite ". ~/.Mfunctions" e pronto.
# Agora é só digitar o nome da função.
#
# DICA: depois de corretamente instalada, use "M"
# para ver as funções disponíveis.
#
# Funções disponíveis neste arquivo:
# + Mecho
# + Mcenter
# + Mclock
# + Mclock2
# + Msetpath
# + Mdica
# + Marrumanome
# + Mnocomments
# + Mcalcula
# + Mcores
#
# Aproveite!
# meleu
#
# P.S.: graças a esse tal de "oupem sórssi" você pode ler
# um código e alterá-lo para que se adeque as suas
# necessidades eu que fique ao seu gosto. Pois foi
# isso que eu fiz aqui! Saí olhando as funções que
# outras pessoas fizeram e arrumei do meu jeito. E
# a minha principal fonte foi o funcoeszz do aurélio.
# veja em: http://verde666.org/zz
#
# imprime em negrito
function Mecho {
echo -e "\e[1m$*\e[m"
}
# imprime em negrito no centro da linha
function Mcenter {
local POS=$[ ( $COLUMNS - `echo -en "$*" | wc -c` ) / 2 ]
Mecho "\e[${POS}C$*"
}
# deixa sempre no cantinho da primeira linha do console:
# "[ hora:minuto dia/mes/ano ]".
# Se houver algum processo em segundo plano (background) ele também indica.
# OBS.: nos emuladores de terminal em que eu testei só funcionou no xterm
# o rxvt não aceita os códigos de salvar e restaurar a posição do cursor
# (respectivamente "\e[s" e "\e[u").
function Mclock {
local CIANO="\e[1;36m"
local AMARELO="\e[1;33m"
local SCOR="\e[m"
alias DiaMesAno='date +'\''%H:%M %e/%m/%y'\'
PROMPT_COMMAND="
JOBS=\$(echo \$(jobs | wc -l))
if [ \$JOBS -ne 0 ]; then
HEADER=\"Jobs: \$JOBS - \$(DiaMesAno)\"
else
HEADER=\"\$(DiaMesAno)\"
fi
POS=\$[ (\$COLUMNS - \$(echo \"\$HEADER\" | wc -c) ) - 3 ]"
PS1="\[\e[s\e[1;0H\e[K\
\e[\$(echo -n \$POS)C\
$CIANO[$AMARELO \$HEADER $CIANO]$SCOR\
\e[u\e[1A\]
$PS1"
echo -e "\nMclock ativado!\n"
}
# Parecido com o Mclock mas fica tudo escrito no centro da primeira linha
# e em um formato mais longo.
function Mclock2 {
local CIANO="\e[1;36m"
local AMARELO="\e[1;33m"
local SCOR="\e[0m"
alias Mdate='date +'\''%H:%M - %A, %e %B %Y'\'
PROMPT_COMMAND="
JOBS=\$(echo \$(jobs | wc -l))
if [ \$JOBS -ne 0 ]; then
HEADER=\"Jobs: \$JOBS - $(Mdate)\"
else
HEADER=\"\$(Mdate)\"
fi
POS=\$[ (\$COLUMNS - \$(echo \"\$HEADER\" | wc -c) ) / 2 ]"
PS1="\[\e[s\e[1;0H\e[K\
\e[\$(echo -n \$POS)C\
$CIANO[$AMARELO \$HEADER $CIANO]$SCOR\
\e[u\e[1A\]
$PS1"
echo -e "\nMclock2 ativado!\n"
}
# Adiciona um diretório na sua variável $PATH
function Msetpath {
local DIR
PATH=${PATH:="/bin:/usr/bin"}
[ $# -eq 0 ] && { echo "PATH = $PATH"; return; }
for DIR in "$@"; do
if [ -d "$DIR" ]; then
PATH="$DIR:$PATH"
else
echo "* * * Erro: $DIR não é um diretório"
continue
fi
done
export PATH
}
# eu tenho no meu home um diretório dicas onde eu vou colocando
# dicas sobre programas diversos.
# o nome dos arquivos são iguais aos nomes dos programas, então
# quando eu me deparo com uma dica sobre o grep, por exemplo, eu
# faço:
# [prompt]$ cat dica_grep >> ~/grep
# esta função serve para visualizar as dicas
# OBS.: o aurélio que me deu ESTA dica do diretório "$HOME/dicas".
# valeu rapaz! ;)
function Mdica {
local DICASDIR=$HOME/dicas
[ "$1" ] || {
Mecho "Uso: Mdica [assunto]\n"
echo "Os assuntos disponíveis são:"
ls $DICASDIR
return
}
more $DICASDIR/$1
}
# renomeia os arquivos que possuem nomes com caracteres feiosos
# fazendo com que letras maiúsculas fiquem minúsculas;
# letras acentuadas fiquem a letra correspondente sem acento;
# e espaços em branco, símbolos e outras coisas feias fiquem
# underline '_'
function Marrumanome {
[ "$1" ] || {
Mecho "Erro: você precisa passar os arquivos que quer renomear";
echo 'Uso: Marrumanome arquivo1 [arquivoN ...]'
return 1
}
local FILE NINICIAL NFINAL DIR
for FILE in "$@"; do
[ -f "$FILE" ] || continue
NINICIAL=`basename "$FILE"`
DIR=`dirname "$FILE"`
NFINAL=`echo "$NINICIAL" | sed '
y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/
y/ÃãÀàÂâÄäÁáÈèÊêËëÉé/aaaaaaaaaaeeeeeeee/
y/ÌìÎîÏïÍíÕõÒòÔôÖöÓó/iiiiiiiioooooooooo/
y/ÙùÛûÜüÚúÇçÑñ/uuuuuuuuccnn/
s/^-/_/
s/[^a-z0-9._-]/_/g'`
[ "$NINICIAL" != "$NFINAL" ] && mv -- "$FILE" "$DIR/$NFINAL"
done
}
# visualiza um arquivo retirando linhas que comecem com um caractere
# de comentário (#) e linhas vazias (linhas com espaços não são
# vazias)
function Mnocomments {
[ "$1" ] || {
Mecho "Erro: falta argumentos"
echo "Uso: Mnocomments arquivo1 [arquivoN ...]"
return
}
# estou usando o more só por causa daqueles ":::::::" que aparecem
# quando é passado mais de um arquivo como parâmetro. ;-)
more $@ | egrep -v "^#|^$"
}
# faz cálculos usando o bc
# só pra não precisar ficar fazendo "echo | bc" toda hora
function Mcalcula {
[ "$1" ] || {
Mecho "Erro: você precisa passar uma expressão"
echo "Uso: Mcalcula "
echo "Exemplo: Mcalcula '4^2+3*(7-4)'"
return 1
}
# mude o valor de "scale" se quiser mais de duas casas decimais
echo "scale=2; $@" | bc
}
# mostra todas as cores do console e seus respectivos códigos.
# mais uma cortesia do aurélio
function Mcores {
for LETRA in `seq 0 7`; do
for BOLD in '' ';1'; do
for FUNDO in `seq 0 7`; do
SEQ="4$FUNDO;3$LETRA"
echo -ne "\e[$SEQ${BOLD}m $SEQ${BOLD:- } \e[m"
done
echo
done
done
}
Se você quer ver umas funções porretas que o aurélio fez conheça as funcoeszz (ver Referências).