Scripts Prontos: Loops bash
Deixe mais simples!

Scripts Prontos: Loops bash

Imagine o seguinte cenário: você quer saber o número de arquivos em 20 diretórios diferentes, todos nomeados de maneira aleatória: SP-1, RJ-3, RS-12....

Não foi fornecido texto alternativo para esta imagem
Diretório Exemplo

A alternativa mais óbvia é entrar nos diretórios individualmente e lançar:

ls -l | wc -l        

Mas fazer isso 20 vezes seria trabalhoso e propenso a erros, felizmente, o shell script oferece uma solução que muitos não conhecem: loops, ou seja, a opção de realizar uma série de comandos repetida e automaticamente.

O loop 'for'

Para resolver o cenário acima usando o "for" você precisa apenas listar os nomes juntamente ao comando. No exemplo abaixo, eu listo os diretórios na chamada do loop e me refiro a eles como "dir", depois, armazeno os resultados individualmente em uma variável "total", a qual eu imprimo na linha seguinte, permitindo uma visualização mais amigável:


for dir in AM-12 ES-87 MG MG-2 MT-01 RJ RJ-12 RJ-3 RS-12 RS-3 RS-12 ES-77 TO MG-20 MT-11 RJ-6 AC-12 PA-3 PA-12 GO-3; do
 total=`ls -l $dir | wc -l`;
 echo "$dir - $total"
done;        

Executando o script acima, teremos:


AM-12 - 12
ES-87 - 0
MG - 140
MG-2 - 14
MT-01 - 90
RJ - 98
RJ-12 - 25
RJ-3 - 10
RS-12 - 0
RS-3 - 67
RS-12 - 23
ES-77 - 11
TO - 24
MG-20 - 91
MT-11 - 12
RJ-6 - 42
AC-12 - 23
PA-3 - 0
PA-12 - 12
GO-3 - 12        

Se você quiser salvar o resultado em um csv para análise, basta trocar o " - " por "," e direcionar o output para o arquivo com ">> .csv"


for dir in AM-12 ES-87 MG MG-2 MT-01 RJ RJ-12 RJ-3 RS-12 RS-3 RS-12 ES-77 TO MG-20 MT-11 RJ-6 AC-12 PA-3 PA-12 GO-3; do
 total=`ls -l $dir | wc -l`;
 echo "$dir , $total"
done >> arquivo.csv;         

Mas e se eu quiser ler apenas os arquivos com determinadas datas, por exemplo: 20221203, 20221204, 202205, etc...? Para isso, podemos usar um loop dentro do outro:


for data in 20221203 20221204 20221205 20221206 20221207; do
 for dir in AM-12 ES-87 MG MG-2 MT-01 RJ RJ-12 RJ-3 RS-12 RS-3 RS-12 ES-77 TO MG-20 MT-11 RJ-6 AC-12 PA-3 PA-12 GO-3; do
  total=`ls -l $dir | grep $data | wc -l`;
  echo "$data - $dir - $total"
 done;
done;        

Teremos como resultado:


20221201 - AM-12 - 1
20221201 - ES-87 - 0
20221201 - MG - 140
20221201 - MG-2 - 14
...
20221202 - AM-12 - 1
20221202 - ES-87 - 0
20221202 - MG - 140
20221202 - MG-2 - 14
...
20221203 - AM-12 - 1
20221203 - ES-87 - 0
20221203 - MG - 140
20221203 - MG-2 - 1
...        

Você pode usar quantos loops quiser, só tome cuidado com seu uso de RAM e CPU.

Mas e se o número de diretórios que eu quiser monitorar for grande, na casa dos milhares talvez? Bem, se os diretórios/arquivos seguirem alguma lógica do tipo: arquivo.log, arquivo.log.1, arquivo.log.2, arquivo.log.3... podemos utilizar uma opção para gerar sequências:


for i in {1..20}; do
  x=`cat arquivo.log.$i | wc -l`;
  echo "arquivo.log.$i , $x";
done;        

Se por algum motivo você quiser utilizar um passo específico (de dois em dois, três em três), basta fazer:


for i in {10..200..10}; do
  x=`cat arquivo.log.$i | wc -l`;
  echo "arquivo.log.$i , $x";
done;        

Esse loop irá iterar por todos os arquivos terminados com um múltiplo de 10 entre 10 e 200. Você pode conferir alguns outros exemplos no artigo abaixo:

Mas e se os arquivos/diretórios não seguiram uma lógica simples? E se eles estiverem distribuídos entre vários diretórios diferentes com nomes aleatórios? Felizmente, o bash já vem com uma opção pronta.

O loop 'while'

Suponha que você queira executar uma mesma ação sobre milhares de arquivos, por exemplo, contar o número de linhas em cada um. Escrever todos os nomes em um único loop não seria viável, obviamente, mas podemos armazená-los em um arquivo "txt" como o exemplo abaixo....


/var/log/monitoracao-1/arquivo_de_log-1.log
/var/log/monitoracao-2/arquivo_de_log.log
/var/log/monitoracao-3/arquivo_de_log.log
/var/log/monitoracao-4/arquivo_de_log.log
/home/joao/desktop/monitoracao-5/arquivo.csv
/home/pedro/desktop/monitoracao-6/arquivo.csv
...        

...e ler esse arquivo com o loop while, para isso, usamos o comando read associado ao "<":


while read line:
 x=`cat $line | wc -l`;
 echo "$line - $x"; 
done < arquivo.txt;        

Basta agora exportar para um csv e você pode monitorar o crescimento dos seus logs tranquilamente.

Por fim, sobra a situação em que você quer que o loop continue executando até que uma condição específica seja atendida. Para isso, basta usarmos uma variável para monitorar a situação monitorada e fazer como no loop abaixo:


num=`ls -l diretorio_qualquer | wc -l`;
while [[ $num -le 200 ]]; do
 sleep 10;
 num=`ls -l diretorio_qualquer | wc -l`;
done;

echo "ALERTA!!!!"        

O loop acima vai contar o número de arquivos em um diretório em intervalos de 10 segundos e caso o número ultrapasse 200, o loop se encerra e um alerta é emitido para o usuário.

Conclusão

Os scripts apresentados aqui são apenas a ponta do iceberg no potencial de loops no Linux. Se deseja fazer algo realmente incrível, pesquise mais sobre o Linux, ou siga Iago Ferreira para mais dicas. O shell script é um mundo de possibilidades para facilitar nossas vidas, cabe a você explorar!

Agradeço a atenção, espero que seja útil.

Iago Ferreira

Devops Engineer | Cloud | SRE | Ajudo profissionais e empresas a migrarem para área de CLOUD/DEVOPS.

2 a

Muito top! Parabéns pelo conteúdo 👏

Entre para ver ou adicionar um comentário

Outras pessoas também visualizaram

Conferir tópicos