A função “for” pode ser usada para executar tarefas repetitivas, como por exemplo:
for arquivo in *.mp3
do
lame -b 64 "$arquivo" "64k-$arquivo"
done
Isto vai gerar uma cópias de todos os arquivos mp3 da pasta atual encodados com bitrate de 64k, gerando arquivos menores, úteis para escutar num MP3 Player com pouca memória, por exemplo.
Se você precisar formatar de uma vez várias partições do HD, criadas através do cfdisk, poderia usar:
for part in {1,2,3,5,6,7}
do
mkreiserfs /dev/hda$part
done
Especificamos aqui um conjunto, que inclui os números 1, 2, 3, 4, 6 e 7, correspondentes às partições que queremos formatar em ReiserFS. Para cada um dos números no conjunto, o for executa o comando mkreiserfs, formatando
cada uma das partições.
Você pode fazer com que o mesmo comando seja executado várias vezes, usando uma variável incremental com o comando “seq”, como em:
for numero in $(seq 1 10)
do
touch arquivo$numero.txt
done
Isto vai fazer com que sejam criados 10 arquivos de texto em branco, numerados de 1 a 10.
O comando cut é outro recurso muito usado e útil. Ele permite “filtrar” a saída de outros comandos, de forma a obter apenas a informação que interessa.
Imagine, por exemplo, que você precisa descobrir o sistema de arquivos que uma determinada partição do sistema está formatada, de forma a usar a informação mais adiante no script.
O comando “mount” mostra todas as partições montadas:
none on /proc type proc (rw,nodiratime)
/sys on /sys type sysfs (rw)
/dev/hda2 on /home type reiserfs (rw,noatime,notail)
/dev/hda3 on /home type ext3 (rw)
/dev/hda6 on /mnt/hda6 type reiserfs (rw)
Digamos que você esteja interessado apenas na partição hda2. O grep permite eliminar as outras linhas, deixando apenas a referente a ela. Use um pipe ( | ) depois do mount para direcionar a saída para o grep:
Mas, como queremos apenas o sistema de arquivos em que a partição está formatada, podemos usar mais um pipe para direcionar a saída para o cut, de forma que ele elimine o resto da linha. Veja que incluí também a função do
sed que elimina espaços repetidos. É importante sempre usá-la em funções que usem o cut para procurar por campos específicos, pois muitos comandos usam espaços de forma não padronizada.
A opção “-f‘ do cut permite especificar os campos que serão mostrados, enquanto a opção “-d” permite especificar o separador entre os campos. No
exemplo usei um -d ” ” para especificar que um espaço separa cada campo e que quero apenas o quinto campo, que é onde está a informação sobre o sistema de arquivos. Da enorme saída do mount, sobra apenas “reiserfs” que é a informação que queremos.
Você pode utilizar qualquer caracter ou string de caracteres como delimitador ao invés do espaço, permitindo localizar campos e expressões dentro de arquivos de configuração.
Usando a opção “-c“, o cut exibe apenas os caracteres indicados. Ela é bem menos usada que o “-f”, pois na prática é complicado se basear em caracteres ao procurar informações em
arquivos, mas ela pode ser útil em algumas funções, como quando o script fizer uma pergunta e a resposta fornecida pelo usuário tiver um tamanho limite, como em:
Aqui, o arquivo de resposta receberá apenas os 5 primeiros caracteres da resposta, não importa o que for digitado.
Mais alguns exemplos úteis:
cut -c 5-: Exibe do quinto caracter em diante, independentemente de quantos existam.cut -d " " -f 5-: Exibe do quinto campo em diante, usando o espaço como delimitador.cut -d "/" -f 1-3: Exibe os três primeiros campos, usando a barra como delimitador (na verdade os dois, pois o cut conta a partir de antes da primeira barra). É bom para filtrar localização de arquivos, por exemplo,
ficando apenas com os primeiros campos. Se o texto original é “/mnt/hda6/arquivos/backup”, depois de passar pelo cut fica apenas “/mnt/hda6”. cut -c -7: Exibe do começo até o sétimo caracter, o mesmo que “cut -c
1-7”.
Uma limitação do cut é que ele não possui uma opção para exibir do final da string até um determinado caracter ou delimitador (apenas do começo até certo ponto), mas é possível burlar isso usando outro comando, o
“rev“, que inverte a ordem dos caracteres. Você pode usá-lo para inverter a string, procurar a partir do início usando o cut e depois inverter de novo. Este é um exemplo de uso, um script que escrevi para baixar
arquivos .torrent:
ARQ2=`echo $arq | sed -r ‘s/ /\\\ /g’`
A primeira linha abre uma janela do kdialog, pedindo o arquivo .torrent a ser baixado. Por causa do “|Arquivos .torrent” a janela só mostra os arquivos com a extensão, o que dá um efeito mais profissional e ajuda e evitar
enganos. A segunda linha substitui todos os espaços no nome do arquivo por “\ “; ou seja, adiciona as barras invertidas, permitindo que usemos os arquivos diretamente no comando do bittorrent, sem precisar usar aspas.
rev /tmp/bt1 | cut -f 2- -d “/” > /tmp/bt2
PASTA=`rev /tmp/bt2`
rm -f /tmp/bt1 /tmp/bt2
Esta é a parte do script que usa o cut e o rev. A variável “$PASTA”, precisa conter apenas a pasta, sem o nome do arquivo. Como não sei quantos caracteres tem o nome do arquivo, nem posso filtrar a partir do final usando o
cut, salvo o conteúdo da variável com o arquivo num temporário, inverto a ordem dos caracteres usando o rev, removo o nome do arquivo usando o sed, desta vez procurando a partir do começo e usando a barra como delimitador e, no final, inverto novamente o
conteúdo do arquivo usando o rev.
Se o arquivo original era “/home/morimoto/ANIMES/[Lunar] Bleach – 62 .avi.torrent”, no final sobra apenas “/home/morimoto/ANIMES/”, que é a pasta onde o arquivo será baixado.
No final, é usada mais uma janela do kdialog, desta vez para perguntar a taxa de upload, e as três variáveis são usadas para montar o comando que baixa o arquivo. Note que o comando é executado dentro de uma janela do Xterm,
de forma que basta fechar a janela quando o download for concluído.
xterm -e “cd $PASTA; btdownloadcurses –max_upload_rate $UPLOAD $ARQ2” &
Vamos a mais um exemplo. Imagine que você precisa de um script para listar os usuários cadastrados no sistema. Você poderia usar o sed para filtrar o conteúdo do arquivo “/etc/shadow”,
o arquivo que contém a lista de usuários e senhas do sistema.
Um exemplo (reduzido) do conteúdo deste arquivo seria:
daemon:*:11453:0:99999:7:::
bin:*:11453:0:99999:7:::
proxy:*:11453:0:99999:7:::
kurumin:gMBaRFGpJx86c:12840:0:99999:7:::
saned:!:12766:0:99999:7:::
Veja que a lista inclui também os usuários ocultos do sistema, usados por programas e serviços, que não interessam neste caso. As linhas referentes a estes usuários ocultos possuem sempre um “!” ou um “*” depois do primeiro
“:”. Podemos usar o sed para filtrar o arquivo, de forma que sobrem apenas as linhas dos usuários válidos (no caso root e kurumin), usando a opção “D” para deletar as linhas que
contenham “!” ou “*”.
Um exemplo de script para fazer isso seria:
sed -e ‘\/*/D’ /etc/shadow > /tmp/usuarios1
# Remove as linhas com “!”
sed -e ‘\/!/D’ /tmp/usuarios1 > /tmp/usuarios2
# Remove o restante da linha, deixando apenas o nome do usuário.
# (o cut mostra apenas o primeiro campo da linha, antes do “:”
cat /tmp/usuarios2 | cut -d: -f1 >> /tmp/usuarios
# usadas de acordo com a situação.
# A primeira, “usuarios” mantém as quebras de linha, com um usuário por
# linha enquanto a “userlist” contém todos os usuários na mesma linha.
usuarios=`cat /tmp/usuarios`
userlist=`echo $usuarios`
# Remove os arquivos temporários
rm -f /tmp/usuarios /tmp/usuarios1 /tmp/usuarios2
kdialog –msgbox “Os usuários atualmente cadastrados no sistema são:
$userlist”
Ao filtrar a saída de comandos que incluam espaços repetidos, use o comando do sed que remove espaços duplicados, como nesta função que diz o número de blocos da partição “/dev/hda1”, filtrando a saída do comando “fdisk
-l”:
Sempre que precisar fazer operações aritméticas dentro de um script, use o comando “bc“. Ele é uma calculadora de modo texto, que permite realizar todo tipo de operações.
Para multiplicar o número dentro da variável $numero por três, o comando seria:
Para dividir $numero por 4:
Por default, o bc trabalha apenas com números inteiros, sempre arredondando os valores das respostas. Para adicionar suporte a casas decimais, ative o matlib, adicionando a opção “-l”, como em:
O bc oferece um número assustador de opções, se você quiser ir além das quatro operações básicas, dê uma olhada no “man bc”.
Outra forma de realizar operações aritméticas é usar o comando “let“. Ele não é tão poderoso quanto o bc (trabalha apenas com números inteiros e as operações básicas), mas é mais
simples de usar e por isso útil para realizar operações simples.
Para aumentar em 1 o valor de uma variável numérica (no caso de um contador, por exemplo):
Para multiplicar o valor por dois:
O comando “import” pode ser usado para tirar screenshots da tela via linha de comando ou via script. Ele pode ser usado, por exemplo, em situações onde você precisar ver o que está
acontecendo na tela para fins de suporte. Para tirar um screenshot, o comando é simplesmente:
Para que o comando funcione, é necessário que ele seja executado dentro da seção gráfica desejada. Um script que ficasse tirando screenshots periódicos da tela, por exemplo, precisaria ser iniciado a partir da pasta
“.kde/Autostart” dentro do home do usuário, e não a partir do “/etc/rc.d/rc.local”, por exemplo.
Mais um problema no caso do script para tirar screenshots é que ele precisaria usar nomes de arquivos com nome diferente para cada screenshot, incluindo informações sobre a data em que foram tirados. Isto pode ser feito
usando o comando “date”.
Em seu formato mais simples, o comando date retorna a data no formato: “Ter Fev 21 13:01:06 BRT 2006”. Mas, é possível configurá-lo para devolver a data num formato mais propício para ser usada em nomes de arquivos, como
“2006-02-21-13.01” (neste caso o comando seria “date +%Y-%m-%d-%H.%M”), atribuir o valor contendo a data corrente a uma variável e usá-la no nome do arquivo. Um script destinado a tirar um screenshot da tela de 1 em 1 minuto, poderia conter:
import -window root screen-$DATA.png
sleep 60
Os screenshots poderiam ser salvos num compartilhamento do servidor, montado em NFS, por exemplo, e removidos no final do dia para não ocuparem muito espaço.
Um problema clássico nos scripts é com relação aos arquivos temporários. Ao usar nomes fixos, é necessário que você sempre remova ou verifique se os arquivos já não existem no começo do script. Existe ainda uma pequena
possibilidade de algum programa malicioso tentar modificar os arquivos temporários, de forma a alterar o comportamento do seu script.
Uma forma de solucionar ambos os programas é usar arquivos temporários com nomes aleatórios, criados usando o comando “mktemp”. No início do script, crie uma variável contendo um arquivo criado através dele:
Os “XXXXXX” serão substituídos por caracteres aleatórios, fazendo com que o nome do arquivo seja algo como “/tmp/rarq.iutCkB”. Para salvar informações dentro do arquivo, use sempre a variável “TMP”, como em:
Não se esqueça de remover o temporário no final do script, usando um “rm -f $TMP” para evitar deixar lixo para trás.