Alexandre Medeiros

Dicas para você passar na LPIC-1 e 2 e outros assuntos de TI

Listando tamanho de arquivo agrupado por extensão

Gerar um relatório as vezes não é a coisa mais fácil e geralmente precisamos ter o máximo de cuidado para que os dados estejam corretos. Nas próximas linhas irei detalhar como cheguei na solução para ter um relatório por tamanho de arquivo agrupado por extensão.

O problema que tive foi com o disco do servidor que chegou a 95% de ocupação. O servidor de arquivos em si possui um Samba e com isso surgiu a necessidade de saber quais extensões de arquivos ocupavam mais espaço.

Primeiramente dividi em pequenas tarefas para chegar no objetivo do relatório por tamanho de arquivo agrupado por extensão em si. A primeira necessidade foi listar todas as extensões de arquivos.

Em suma, todo o passo a passo será explicado minuciosamente para que qualquer um possa entender.

Antes de mais nada, fique à vontade para deixar nos comentários quaisquer dúvidas ou sugestões de melhoria.

Passo 1 – Listar por extensão de arquivo

Para encontrarmos todos os arquivos iremos utilizar o comando find:

Para saber mais sobre o comando clique aqui.

# find . -type f

O ponto (.) informa que iremos procurar a partir do diretório local e o parâmetro type informa se queremos:

  • arquivo = f [regular file]
  • diretório = d [directory]
  • link simbólico = l [symbolic link]
  • caracter especial = c [character special
  • bloco especial = b [block special]
  • FIFO = p [First In First Out]
  • socket = s [socket]

Ao executarmos o comando find na saída serão listados todos os arquivos. Segue um exemplo:

# find . -type f
./Downloads/google-cloud-sdk/lib/googlecloudsdk/schemas/dataproc/v1/OrderedJob.yaml
./Downloads/google-cloud-sdk/lib/googlecloudsdk/schemas/dataproc/v1/ParameterValidation.yaml
./Downloads/google-cloud-sdk/lib/googlecloudsdk/schemas/dataproc/v1/PigJob.yaml
./Downloads/google-cloud-sdk/lib/googlecloudsdk/schemas/dataproc/v1/PySparkJob.yaml
./Downloads/google-cloud-sdk/lib/googlecloudsdk/schemas/dataproc/v1/RegexValidation.yaml
./Downloads/google-cloud-sdk/lib/googlecloudsdk/schemas/dataproc/v1/SecurityConfig.yaml
./Downloads/google-cloud-sdk/lib/googlecloudsdk/schemas/dataproc/v1/SoftwareConfig.yaml
./Downloads/google-cloud-sdk/lib/googlecloudsdk/schemas/dataproc/v1/SparkJob.yaml
./Downloads/google-cloud-sdk/lib/googlecloudsdk/schemas/dataproc/v1/SparkSqlJob.yaml
./Downloads/google-cloud-sdk/lib/googlecloudsdk/schemas/dataproc/v1/TemplateParameter.yaml
./Downloads/google-cloud-sdk/lib/googlecloudsdk/schemas/dataproc/v1/ValueValidation.yaml
./Downloads/google-cloud-sdk/lib/googlecloudsdk/schemas/dataproc/v1/WorkflowTemplate.yaml
./Downloads/google-cloud-sdk/lib/googlecloudsdk/schemas/dataproc/v1/WorkflowTemplatePlacement.yaml
./Downloads/google-cloud-sdk/lib/googlecloudsdk/schemas/dataproc/v1beta2/AcceleratorConfig.yaml
./Downloads/google-cloud-sdk/lib/googlecloudsdk/schemas/dataproc/v1beta2/AllocationAffinity.yaml
./Downloads/google-cloud-sdk/lib/googlecloudsdk/schemas/dataproc/v1beta2/AutoscalingConfig.yaml
./Downloads/google-cloud-sdk/lib/googlecloudsdk/schemas/dataproc/v1beta2/AutoscalingPolicy.yaml

Posteriormente iremos utilizar o | (pipe) que é uma ferramenta muito poderosa pois podemos passar o resultado de um comando para outro. No caso acima todo resultado do comando find irá ser redirecionado para o comando egrep.

Para saber mais do comando egrep clique aqui.

# find . -type f |  egrep -o "\.[a-zA-Z0-9]+$"

O comando egrep procura por um texto em qualquer saída ou arquivo de entrada e pode lidar com expressões regulares. O parâmetro -0 (only matching) imprime apenas a parte correspondente das linhas.

Explicando a expressão regular “\.[a-zA-Z0-9]+$”:

  • \. = Busca pelo caractere escapado (.). Caracter escapado é considerado literal.
  • [ ] = Busca por um conjunto de caracteres:
    • a-z = Busca por caracteres de a até z
    • A-Z = Busca por caracteres de A até Z
    • 0-9 = Busca por caracteres de 0 até 9
  • + = Quantificador. Corresponde a um ou mais dos símbolos anteriores.
    Por exemplo:

    • b\w+
    • boa bom bula buraco …
  •  $ = Final. Corresponde ao final da string, ou fim da linha.

Ou seja, iremos procurar pela extensão do arquivo que nada mais é do que tudo após o ponto.

Assim o resultado será redirecionado para o comando sort.

Para saber mais do comando sort clique aqui.

# find . -type f |  egrep -o "\.[a-zA-Z0-9]+$" | sort -u

O comando sort classifica arquivos de texto e binários por linhas. O parâmetro -u (unique) suprime todas as linhas que possuem uma chave igual a uma já processada, para não haver repetição.

A próxima parte do código é bem extensa, então vamos lá…

Passo 2 – Procurar pela extensão e printar na tela

Nesse meio tempo iremos entender que o resultado dos comandos anteriores irá procurar por tudo o que tiver após o ponto (.) no arquivo e depois irá classificar e eliminar qualquer repetição. O resultado agora irá ser redirecionado para o comando xargs.

# find . -type f |  egrep -o "\.[a-zA-Z0-9]+$" | sort -u | xargs -I '%' find . -type f -name "*%" -exec du -ch {} + -exec echo % \;

Logo, o comando xargs é utilizado quando temos uma lista de itens a ser passado para o próximo comando maior do que o shell pode trabalhar. O parâmetro -I informa ao xargs que execute para cada resultado de entrada, enviando para o próximo comando find, uma ou mais ocorrências de % (o caracter % significa todos os caracteres encontrados).

Para saber mais do comando xargs clique aqui.

Em seguida o comando find irá procurar por todos os arquivos passados pelo xargs.

  • -exec <comando> {} + Essa variante da ação -exec executa o comando especificado nos arquivos encontrados, mas a linha de comandos é criada anexando cada nome de arquivo encontrado no final. O número total de invocações do comando será muito menor que o número de arquivos correspondentes. A linha de comando é construída da mesma maneira que o xargs cria suas linhas de comando. A string {} é substituída pelo nome do arquivo encontrado atual sendo processado.

E irá executar dois comandos a partir da ação:

  • du -ch
    • O comando du (disk usage) irá calcular o tamanho de cada arquivo passado pela substituição da string {}, ou seja, du -ch <arquivo>. O parâmetro -c (total) e o h (human readable) irá printar o tamanho do arquivo nos formatos K, M e G.
    • Para saber mais do comando du clique aqui.
  • echo  %
    • Irá mostrar a linha de texto a todos os caracteres encontrados  relacionado ao comando xargs (extensão de arquivo).
    • Para saber mais do comando echo clique aqui.

Ao final temos que escapar com o \;

O ponto e vírgula finaliza o comando executado pelo exec. Ele precisa ser escapado com \ para que o shell encontre o caracter e não o trate como seu próprio caractere especial.

Passo 3 – Manter a extensão do arquivo e o tamanho do arquivo

Abaixo segue o comando completo:

# find . -type f |  egrep -o "\.[a-zA-Z0-9]+$" | sort -u | xargs -I '%' find . -type f -name "*%" -exec du -ch {} + -exec echo % \; | egrep "^\.[a-zA-Z0-9]+$|total$" | uniq | paste - -

Iremos explicar a partir do segundo comando egrep. A diferença para o primeiro é que o caracter ^ indica o começo da string. Depois ele vai escapar o caracter ponto (.), ou seja, iremos pegar tudo o que tiver uma string com ponto. O restante é qualquer formação de string após o ponto, como explicado no primeiro egrep.

O pipe (|) nesse caso não é um redirecionamento pois está sendo tratado como expressão regular do egrep. O pipe nesse caso indica alternação. Ele atua como um operador booleano OR. No final fechamos o final da string novamente com o $.

O comando uniq sem opções, as linhas correspondentes são mescladas à primeira ocorrência.

E no final, o comando paste irá ler todos os argumentos. Para cada linha correspondente, o paste irá anexar o conteúdo da saída padrão. Quando utilizamos o comando sem mencionar arquivo e com o caracter (-), como foi o caso, o comando irá ler da saída padrão e não de um arquivo.

Para saber mais do comando paste clique aqui.

Prontinho! Concluindo, ao final temos o nosso relatório por tamanho de arquivo agrupado por extensão conforme exemplo abaixo:

# find . -type f |  egrep -o "\.[a-zA-Z0-9]+$" | sort -u | xargs -I '%' find . -type f -name "*%" -exec du -ch {} + -exec echo % \; | egrep "^\.[a-zA-Z0-9]+$|total$" | uniq | paste - -

.css	20K	total
.dat	1.2M	total
.doc	1.8G	total
.DOC	216K	total
.docx	68M	total
.jgwx	288K	total
.JGwx	4.0K	total
.jpg	3.9G	total
.JPG	2.0G	total
.jpgw	12K	total
.js	1.1M	total
.kml	73M	total
.pdf	11G	total
.PDF	81M	total
.tmp	35M	total
.ts	12K	total
.txt	12M	total
.TXT	24K	total
.ui	4.0K	total
.xls	4.5M	total
.XLS	232K	total
.xlsx	416K	total
.xlt	36K	total
.xml	47.7M	total
.xsd	4.0K	total
.zip	675M	total

Se você quiser aprender mais sobre o editor de texto vim clique aqui.

Por último, compartilhe esse artigo com alguém ou comente com alguma dúvida ou sugestão.