sergioaraujo

 

Shell_Script

Page history last edited by Sérgio Luiz Araújo Silva 3 mos ago


Introdução

Esta página contém uma série de scrips shell para usos diversos. Cadastre-se também na lista de shell script do yahoo http://br.dir.groups.yahoo.com/group/shell-script/ e descubra tudo que pode fazer com shell script

 

Listas e dicas

 

Scripts

 

Manual shell script

Essa apostila está em formato *.ps no kurumin linux use o comando ps2pdf para gerar um pdf.

 

ps2pdf aposhell.ps

 

Atalhos do konsole

 

^ ---> leia Control

^L ........... limpar a tela

^w ........... apagar palavra anterior

^e ........... vai para o final da linha

^a ........... vai para o começo da linha

^f ........... avança um caractere

^b ........... recua um caractere

Mf ........... avança uma palavra

Mb ........... recua uma palavra

^u ........... recorta do ponto atual até o começo da linha

^y ........... cola o que foi recortado

^d ........... faz logof

^k ........... recorta até o final da linha

^r ........... abre o histórico no modo de procura inversa

M.  .......... recupera o último parâmetro do último comando

 

modificando a variável $PS1

 

$PS1 é o prompt, veja um exemplo de configuração desta variável com cores

 

export PS1='[�33[01;33m]t [�33[01;32m]u@h �33[01;34m]w $ [�33[00m]'/*{{{*//*}}}*/ 

 

 

Testando variáveis

 

#!/bin/ksh
# twofiles script handles two files named on the command line
# a usage function to display help for the hapless user
# plus an additional error message if it has been filled in
usage ()
{
echo "twofiles"
echo   "usage: twofiles file1 file2"
echo   "Processes two files"
echo " "
echo $errmsg
}
# test if we have two arguments on the command line
if [ $# != 2 ]
then
usage
exit
fi
# test if file one exists and send an additional error message
# to usage if not found
if [ ! -f $1 ]
then
errmsg=${1}": File Not Found"
usage
exit
fi
# same for file two
if [ ! -f $2 ]
then
errmsg=${2}": File Not Found"
usage
exit
fi
# we are ok at this point so continue processing here

 

Comparando números

 

-eq Igual

!= Diferente

-gt Maior

-lt Menor

 

Mais comparações

 

-o Ou

-d Se for um diretório

-e Se existir

-z Se estiver vazio

-f Se contiver texto

-o Se o usuário for o dono

-r Se o arquivo pode ser lido

-w Se o arquivo pode ser alterado

-x Se o arquivo pode ser executado

 

Criando uma pasta rapidinho

 

[ -d dir ] || mkdir dir ; cd dir

 

 

 

 

[-n] STRING
Tamanho da String é diferente de zero
-z STRING
Tamanho da String é zero
STRING1 = STRING2
Strings são iguais
STRING1 != STRING2
Strings não são iguais
NUMERO1 -eq NUMERO2
NUMERO1 igual a NUMERO2
NUMERO1 -ge NUMERO2
NUMERO1 igual e/ou mair que NUMERO2
NUMERO1 -gt NUMERO2
NUMERO1 maior que NUMERO2
NUMERO1 -le NUMERO2
NUMERO1 menor e/ou igual a NUMERO2
NUMERO1 -lt NUMERO2
NUMERO1 menor que NUMERO2
NUMERO1 -ne NUMERO2
NUMERO1 diferente de NUMERO2
if [ "texto" = "texto" ]; then
echo "o texto é igual";
fi
if [ 1 -gt 5 ]; then
echo "1 é maior que 5";
fi
if [ "a" = "3" ] || [ "a" = "b" ]; then
echo "a não é igual a 3 ou c";
elif [ "a" = "c" ]  || [ "a" = "d" ]; then
echo "a não é igual a c ou d";
else
echo "A é diferente de 3,c,b,d";
fi

 

Testando se um arquivo está vazio

 

[ -s arquivo ] && echo nao vazio || echo arquivo vazio

 

Permitindo somente uma instância de um script

Às vezes você tem um script e quer que ele não possa ser executado

mais de uma vez ao mesmo tempo. A solução

 

 

LOCK_FILE=/tmp/.lock
(set -C; :  > $LOCK_FILE) 2> /dev/null
if [  $? != "0" ];  then
echo "Lock File exists - exiting"
exit 1
fi
# Do useful stuff
trap  'rm $LOCK_FILE' EXIT

 

Permitindo a execução somente pelo root

Há scripts que só podem ser executados pelo root

para verificar faça

 

 

# Check the script is being run by root
if  [ `id -u` != "0" ];  then
echo "This script must be run as root"
exit  1
fi 

 

#!/bin/bash

CONTADOR=0

while $CONTADOR -lt 10 ; do

 

echo "Contador em: $CONTADOR";

let CONTADOR=CONTADOR+1;

done

 

enquanto $CONTADOR menor que 10 ; faça

 

imprima "Contador em: $CONTADOR";

imcremente 1 no $CONTADOR;

feito

 

 

 

 

 

Estruturas

 

case $1 in
parametro1) comando1 ; comando2 ;;
parametro2) comando3 ; comando4 ;;
*) echo "Você tem de entrar com um parâmetro válido" ;;
esac
if [ -z $1 ]; then
echo "Você tem de entrar com um parâmetro válido"
exit
elif [ $1 = "parametro1" ]; then
comando1
comando2
elif [ $1 = "parametro2" ]; then
comando3
comando4
else
echo "Você tem de entrar com um parâmetro válido"
fi
for i in *
do
cp $i $i.backup
mv $i.backup /usr/backup
done
for original in *; do
resultado=`echo $original |
tr '[:upper:]' '[:lower:]'`
if [ ! -e $resultado ]; then
mv $original $resultado
fi
done

 

 

O comando test

Os colchetes são um aliás para o comando test

 

[[ string =~ regex ]]
# testa se o usuário digitou um parâmetro "$1"
if [ -z "$1" ]; then
echo '   uso: matar programa '
exit
fi

 

 

Um jeito direferente de usar o comando mkdir

 

mkdir -p teste/{docs/{img/{fotos/,wallpapers/,icons/},man/,textos/{bv/,teste/}}}

 

Exemplos

 

ping -c 2 www.google.com > &> /dev/null && 
echo "google respondeu" || echo "rost fora do ar"
google respondeu

 

Somando números de 1 a 100

 

seq -s+ 100 | bc

 

 

Controle de fluxo

 

#!/bin/bash
if [ -e $linux ]
then
echo 'A variável $linux existe.'
else
echo 'A variável $linux não existe.'
fi
Exemplo usando operadores
#!/bin/bash
a=1
b=2
if [ $a -lt $b ]
then
echo '$a é menor que $b!'
elif [ $a -gt $b ]
then
echo '$a é maior que $b!'
elif [ $a -eq $b ]
then
echo '$a é igual a $b!'
fi

====================

Gerador de números aleatórios

====================

 

echo $((RANDOM%Limite))
Onde limite+1 é até que número o shell deverá gerar números aleatórios
E se quiser armazenar o valor gerado:
Valor=$((RANDOM%Limite))
$((RANDOM%5+1))
gera números de 1 a 5
===================================
Para gerar um número aleatório entre -10 e 10
number=$(($((RANDOM%21))-10))

====================

Fluxo com o for

====================

 

for i in *
do
cp $i $i.backup
mv $i.backup /usr/backup
done
====================
#!/bin/bash
if [ -e $linux ]
then
echo 'A variável $linux existe.'
else
echo 'A variável $linux não existe.'
fi
Exemplo usando operadores
#!/bin/bash
a=1
b=2
if [ $a -lt $b ]
then
echo '$a é menor que $b!'
elif [ $a -gt $b ]
then
echo '$a é maior que $b!'
elif [ $a -eq $b ]
then
echo '$a é igual a $b!'
fi

 

=====================

Fluxo com while

=====================

 

O while testa continuamente uma expressão, até que ela se torne falsa. Exemplo:
variavel="valor"
while [ $variavel = "valor" ]; do
comando1
comando2
done

 

 

Ufa! Como você viu tem coisa prá chuchu, e como eu te disse no início,

o nosso if é muito mais poderoso que o dos outros. Vamos ver em uns

exemplos como isso tudo funciona, primeiramente testaremos a

existência de um diretório:

 

Exemplos:

 

 

if test -d lmb

then

cd lmb

else

mkdir lmb

cd lmb

fi

 

No exemplo, testei se existia um diretório lmb definido, caso negativo

(else), ele seria criado. Já sei, você vai criticar a minha lógica

dizendo que o script não está otimizado. Eu sei, mas queria que você o

entendesse assim, para então poder usar o ponto-de-espantação (!) como

um negador do test. Veja só:

 

 

if test ! -d lmb

then

mkdir lmb

fi

cd lmb

 

e utilizando a nova sintaxe, vamos fazê-lo assim:

 

 

if ! -d lmb

then

mkdir lmb

fi

cd lmb

 

 

Isso também poderia ser escrito da seguinte maneira:

 

 

! -d lmb && mkdir lmb

cd dir

 

Ou ainda retirando a negação (!):

 

 

-d lmb || mkdir lmb

cd dir

 

Neste caso, se o cd fosse mal sucedido, seria criado o diretório lmb

mas não seria feito o cd para dentro dele. Para executarmos mais de um

comando desta forma, é necessário fazermos um grupamento de comandos,

e isso se consegue com o uso de chaves ({ }). Veja como seria o

correto:

 

 

cd lmb ||

{

mkdir lmb

cd lmb

}

 

Ainda não está legal, porque caso o diretório não exista, o cd dará a

mensagem de erro correspondente. Então devemos fazer:

 

 

cd lmb 2> /dev/null ||

{

mkdir lmb

cd lmb

}

 

 

==============================================

Para pegar uma variável digitada pelo usuário

==============================================

 

read -p "digite o seu nome: " nome

 

Combinando comandos

O arquivo de configuração do estilos do firefox (para páginas) é nomeado como: userContent.css para buscalo uso o parâmetro '-iname' do find, mas às vezes mantenho cópias em outros locais, para evitar erros busco em minha pasta pessoal por uma pasta que tem um número aleatório no começo e no final a palavra default.

 

cp $(find ~/ -iname usercontent.css | grep default) /home/sergio/Desktop/

 

 

 

 

 

 

 

Arrays

O que você quer fazer? O BASH não oferece funções para tratar arrays.

Mas um array é algo assim:

 

$ array=( A B C D )
$ echo ${array[0]}
A
$ echo ${array[1]}
B
$ echo ${array[@]}
A B C D
VAR=($(ls *.html))  --> gera um array
echo ${VAR[0]}

 

=====================================

Script para criar 100 arquivos txt

=====================================

 

#!/bin/bash
for ((i=1; i<=100; i++)); {
touch arquivo${i}.txt
echo "arquivo${i}.txt" >> arquivo${i}.txt
}

 

 

 

============================================================

Grupos de comandos Expansão de strings e nomes de arquivos

============================================================

 

O Bash permite agrupar comandos, que desse modo são executados como uma única
unidade. Podemos agrupar os comandos de duas formas:
1) Agrupamento por parênteses, "( )": Comandos colocados entre parênteses e
separados por ponto-e-vírgula, ";", são agrupados e executados serialmente
invocando um subshell. Exemplo:
# (ls; du; find -name *.txt)   
2) Agrupados por chaves, "{ }":
Comandos colocados entre chaves e separados por ponto-e—vírgula, ";", são
agrupados e executados serialmente no shell corrente. Exemplo:
# {ls; du; find -name *.txt}
Você deve estar pensando: "Para que eu agruparia meus comandos? Para deixá-los mais bonitos?" Não!
A vantagem de vários comandos agrupados pode ser vista quando precisamos
desviar a saída desses comandos. Imagine que você precise fazer um script para
executar vários comandos e obter a saída de erros de cada comando colocado no
script. Seria assim:
...
comando1 2>erros.txt
comando2 2>>erros.txt
comando3 2>>erros.txt
comando4 2>>erros.txt
...
Com o agrupamento isso fica mais fácil e simples:
...
(
comando1 ; 
comando2 ;
comando3 ;
comando4 ;
) 2>erros.txt
...
Observe que no primeiro exemplo desviamos o erro para cada comando e no segundo
exemplo o desvio foi feito para todos os comandos em uma única vez.
Se esse exemplo fosse passado para a linha de comando ficaria desta forma: exemplo 1:
# comando1 2>erros.txt; comando2 2>>erros.txt ; comando3 2>>erros.txt comando4 >>erros.txt
exemplo 2:
#(comando1;comando2;comando3;comando4;) 2> erros.txt
Você concorda que, com agrupamento, a linha de comando fica até mais legível!
Agora vamos imaginar que você precise tratar a saída de vários comandos, por
exemplo, alterar de minúsculo para maiúsculo. Você poderia escrever assim:
# cat /etc/hosts | tr a-z A-Z > saida.txt ; 
cat /etc/resolv.conf |tr a-z A-Z >>saida.txt ; 
cat /etc/sysconfig/network | tr a-z A-Z >>saida.txt
Mas o ideal seria:
# (cat /etc/hosts ; cat /etc/resolv.conf ; 
cat /etc/sysconfig/network; )| tr a-z A-Z >>saida.txt
No segundo exemplo, além de ficar mais legível, o comando "tr" é executado uma
única vez, já no primeiro exemplo cada um dos comandos será executado.
A diferença entre os grupos criados com parênteses, "( )", ou os criados com
chaves, "{ }", pode ser vista no comando abaixo:
# VAR="ANTES";(VAR="DEPOIS";VAR="ADIANTE";); echo $VAR
ANTES
# VAR="ANTES";{VAR="DEPOIS";VAR="ADIANTE";}; echo $VAR
ADIANTE
Observe que no exemplo escrito com parênteses a variável VAR retornou ao mesmo
valor que fora atribuído antes de executar o grupo de comandos. Isso se deve ao
fato de que os comandos são executados em subshell. Já no exemplo escrito com
chaves a variável VAR retornou ao último valor que fora atribuído, porque
grupos feitos com chaves são executados no shell corrente.
Expansão de strings
Expansão de strings é um mecanismo que combina uma expressão inicial com um
conjunto de caracteres. Exemplo:
#echo a{1,2,3}
a1 a2 a3
As combinações são feitas entre os elementos que estão entre as chaves
separados por vírgula, da esquerda para a direita.
Podemos combinar mais que um conjunto de caracteres simultaneamente:
# echo a{1,2,3}b{1,2,3}
a1b1 a1b2 a1b3 a2b1 a2b2 a2b3 a3b1 a3b2 a3b3
Combinar dois conjuntos separadamente também é possível, basta colocar os
conjuntos entre chaves e separá-los por vírgula.
# echo {a{1,2,3},b{1,2,3}}
a1 a2 a3 b1 b2 b3
A grande vantagem da expansão está na expansão de nomes de arquivos, que é
utilizada em comandos que recebem como parâmetro um ou mais nome de arquivos.
Exemplo:
# ls /dev/hda
| |––> Este é o parâmetro do ls que deve ser um diretório ou um arquivo Imagine
que você queira listar todos os arquivos do diretório /dev que inicie com hda e
termine com 1, 2 ou 3.
# ls /dev/hda{1,2,3}
/dev/hda1 /dev/hda2 /dev/hda3
Podemos combinar dois conjuntos também:
# ls /dev/{hda{1,2,3},hdb{1,2,3}}
/dev/hda1 /dev/hdb1
/dev/hda2 /dev/hdb2
/dev/hda3 /dev/hdb3
Adicionar metacaracteres também é possível:
# ls /dev/{hd?{1,2,3}}
/dev/hda1 /dev/hdb1 /dev/hdc1 /dev/hdd1
/dev/hda2 /dev/hdb2 /dev/hdc2 /dev/hdd2
/dev/hda3 /dev/hdb3 /dev/hdc3 /dev/hdd3
Os metacaracteres suportados em expansão são:
* — Um ou mais caracteres
# ls /dev/{hd{a,b,c}*}
/dev/hda1 /dev/hdb1 /dev/hdc1 
/dev/hda11 /dev/hdb11 /dev/hdc11 
/dev/hda2 /dev/hdb2 /dev/hdc2 
/dev/hda3 /dev/hdb3 /dev/hdc3
? — Exatamente um caractere
# ls /dev/{hd{a,b,c}?}
/dev/hda1 /dev/hdb1 /dev/hdc1 
/dev/hda2 /dev/hdb2 /dev/hdc2 
/dev/hda3 /dev/hdb3 /dev/hdc3
[abc] — Combina com a, b ou c
# ls /dev/{hd[abc]{1,2,3}}
/dev/hda1 /dev/hdb1 /dev/hdc1
/dev/hda2 /dev/hdb2 /dev/hdc2
/dev/hda3 /dev/hdb3 /dev/hdc3
[a-z] — Combina o range de "a" a "z"
# ls /dev/{hd[a-c]{1,2,3}}
/dev/hda1 /dev/hdb1 /dev/hdc1
/dev/hda2 /dev/hdb2 /dev/hdc2
/dev/hda3 /dev/hdb3 /dev/hdc3
[!a-z] — Não combina o range de "a" a "z"
# ls /dev/{hd[!a-c]{1,2,3}}
/dev/hdd1 /dev/hde1 /dev/hdf1
/dev/hdd2 /dev/hde2 /dev/hdf2
/dev/hdd3 /dev/hde3 /dev/hdf3
Espero ter contribuído mais um pouco para o aprendizado dos leitores.
Até a próxima edição!

 

Fazendo testes antes de executar um script

fonte: http://br.geocities.com/cesarakg/tips-shell-programming.html

 

Testando argumentos de linha de comando e modo de usar
Quando você escreve um shell script, os argumentos são normalmente necessários para que o script funcione corretamente. Para garantir que os argumentos façam algum sentido, é geralmente necessário validar os mesmos.
Testar para ver se há argumentos suficientes é geralmente o método mais fácil de validação. por exemplo, se você criou um script shell que pede dois nomes de arquivos para operar, teste a existência de dois argumentos na linha de comando. para fazer isto no Bourne e no Korn shell, verifique o valor de $# -- uma variável que contém a contagem de argumentos, além do próprio comando. É também uma boa pratica incluir uma mensagem que detalhe as razões por que o comando falhou. Isto é criado em uma função usage.
O script twofiles abaixo, testa se há dois argumentos na linha de comando:
#!/bin/ksh
# twofile script handles two files named on the command line
# a usage function to display help for the hapless user
usage ()
{
echo "twofiles"
echo   "usage: twofiles file1 file2"
echo   "Processes two files"
}
# test if we have two arguments on the command line
if [ $# != 2 ]
then
usage
exit
fi
Uma prática mais segura é validar o máximo que você puder antes de executar alguma coisa. A seguinte versão de twofiles verifica a contagem de argumentos e testa os dois arquivos. Se o arquivo 1 não existe ( if [ ! -f $1 ]) uma mensagem de erro é configurada, uma mensagem de uso é apresentada, e o programa termina. O mesmo é feito para o arquivo 2:
#!/bin/ksh
# twofiles script handles two files named on the command line
# a usage function to display help for the hapless user
# plus an additional error message if it has been filled in
usage ()
{
echo "twofiles"
echo   "usage: twofiles file1 file2"
echo   "Processes two files"
echo " "
echo $errmsg
}
# test if we have two arguments on the command line
if [ $# != 2 ]
then
usage
exit
fi
# test if file one exists and send an additional error message
# to usage if not found
if [ ! -f $1 ]
then
errmsg=${1}": File Not Found"
usage
exit
fi
# same for file two
if [ ! -f $2 ]
then
errmsg=${2}": File Not Found"
usage
exit
fi
# we are ok at this point so continue processing here
Note que no Korn shell você pode usar a sintaxe de teste de colchetes duplos, que é mais rápida. O colchete simples na verdade chama um programa test para testar os valores, enquanto que com o colchete duplo o teste é implementado no Korn shell e não precisa chamar um programa separado.
O teste de colchete duplo não funciona no Bourne shell:
if [[ $# != 2 ]]
ou
if [[ ! -f $1 ]]
ou
if [[ ! -f $2 ]]
Esta validação pode evitar erros posteriores na lógica do programa quando subitamente percebe-se que um arquivo está faltando. Considere isto como uma boa prática de programação.

 

Atalhos do bash

 

ATALHOS DO BASH
Ctrl + Alt + BackSpace : reinicia o X
Ctrl + Alt + Del : reinicia o sistema em modo texto
Ctrl + Alt + F''x'' : muda o shell (F1 – F6 (texto), F7 (gráfico))
Alt + F''x'' : alterna o shell (modo texto)
Alt + B : move o cursor do console para a palavra anterior
Alt + F : move o cursor do console para a palavra seguinte
Ctrl + A : vai para o início da linha
Ctrl + E : vai para o fim da linha
Ctrl + C : pára o comando
Ctrl + D : logout
Ctrl + W : apaga do cursor até o início da palavra
Ctrl + U : apaga do cursor até o início da linha
Ctrl + K : apaga do cursor até o fim da linha
Ctrl + L : clear
Ctrl + R : busca incremental no hitórico de comandos
Ctrl + T : inverte caractere sob o cursor com o anterior
Ctrl + Y : re-inserir o último texto apagado
Ctrl + Z: colocar processo em background
Shift + Page(UP/DOWN) : navega pelo shell
!''x'': repete o último comando (onde ''x'' é o comando a ser chamado – Exemplo: !mount)
TAB : autocompletar 

Criando uma árvore de diretórios com um único comando

 

mkdir -p {.wiki/,.vim/{plugin/,syntax},docs/{img/{fotos/,wallpapers/,icons},textos/{artigos/,man/{shell/,vim/,}}}}
No comando acima são criadas três pastas
.wiki (oculta)
.vim - contendo as subpastas plugin e syntax
docs contendo: img (fotos wallpapers e icons) textos contendo (argigos) e (man (shell e vim)

 

Como guardar variáveis em arquivos

 

use  . /caminho/para/arquivo
Note o espaço entre o ponto e a barra

 

Usando cores

Fonte: http://www.vivaolinux.com.br/artigos/impressora.php?codigo=1908

 

echo -e "Viva o �33[01;32mLinux�33[01;37m"
Observem no exemplo os trechos em negrito e reparem que são eles um dos temas do nosso artigo. Tentarei explicar o que vemos:
* "�33": ainda não consegui encontrar o real motivo de usar isto, mas é obrigatório para usar as cores, se trocar por outra coisa dará tudo errado;
* "01"( estilo): significa que nosso texto será em negrito (bold);
* "32m" (cor do texto): 32 representa a cor vermelha e o "m" indica o fim da expressão e após ele você já poderá incluir o texto que bem desejar; 
Meio complicado ainda né!? Mas vai abaixo os dados que certamente irão ajudar a se organizar:

 

Estilos Cores de texto Cores de fundo
00: Nenhum 30: Preto 40: Preto
01: Negrito 31: Vermelho 41: Vermelho
04: Sublinhado 32: Verde 42: Verde
05: Piscante 33: Amarelo 43: Amarelo
07: Reverso 34: Azul 44: Azul
08: Oculto 35: Magenta (Rosa) 45: Magenta (Rosa)
  36: Ciano (Azul Ciano) 46: Ciano (Azul Ciano)
  37: Branco 47: Branco

 

Filtrando linhas de um arquivo

 

Re: [shell-script] Filtrar linhas no arquivo texto
Acho que um sed + ER fica legal:
$ cat test
documento_0012526A.odt
documento_0035555A.odt
documento_0054443A.odt
documento_0022222A.odt
documento_0034344A.odt
documento_0055555A.odt
$ sed 's/^documento_(.*).odt$/1/' test
0012526A
0035555A
0054443A
0022222A
0034344A
0055555A

 

Named Pipes

Fonte: http://www.dicas-l.com.br/cantinhodoshell/cantinhodoshell_20070520.php

Autor: Júlio César Neves

 

$ cat <(ls -l)
Resultará no comando ls -l executado em um subshell como é normal, porém redirecionará a saída para um named pipe temporário, que o Shell cria, nomeia e depois remove. Então o cat terá um nome de arquivo válido para ler (que será este named pipe e cujo dispositivo lógico associado é /dev/fd/63), e teremos a mesma saída que a gerada pela listagem do ls -l, porém dando um ou mais passos que o usual. 

Veja mais...

 

veja também

 

Comments (0)

You don't have permission to comment on this page.