estatísticas recursivas sobre tipos de arquivos no diretório?

52

Eu fiz um site para um projeto de conversão. Gostaria de fazer algumas estatísticas sobre os tipos de arquivos lá existentes - por exemplo, 400 .html files, 100 .gif , etc. O que é uma maneira fácil de fazer isso? Tem que ser recursivo.

Edit: Com o script que maxschelpzig postou, estou tendo alguns problemas devido à arquitetura do site que eu escalei. Alguns dos arquivos são do nome *.php?blah=blah&foo=bar com vários argumentos, portanto, eles são considerados exclusivos. Portanto, a solução precisa considerar *.php* como sendo todos do mesmo tipo, por assim dizer.

    
por user394 10.08.2011 / 20:53

4 respostas

79

Você pode usar find e uniq para isso, por exemplo:

$ find . -type f | sed 's/.*\.//' | sort | uniq -c
   16 avi
   29 jpg
  136 mp3
    3 mp4

Explicação do comando

  • find recursivamente imprime todos os nomes de arquivos
  • sed exclui de cada nome de arquivo o prefixo até a extensão do arquivo
  • uniq assume entrada classificada
    • -c faz a contagem (como um histograma).
por 10.08.2011 / 20:57
7

Com zsh:

print -rl -- **/?*.*(D.:e) | uniq -c |sort -n

O padrão **/?*.* corresponde a todos os arquivos que têm uma extensão, no diretório atual e seus subdiretórios recursivamente. O qualificador de glob D let zsh percorre diretórios ocultos e considera arquivos ocultos , . seleciona apenas arquivos regulares. O modificador de histórico mantém apenas a extensão do arquivo. print -rl imprime uma correspondência por linha. uniq -c conta itens idênticos consecutivos (o resultado glob já está classificado). A chamada final para sort classifica as extensões usando contagem.

    
por 11.08.2011 / 00:16
1

Este one-liner parece ser um método bastante robusto:

find . -type f -printf '%f\n' | sed -r -n 's/.+(\..*)$//p' | sort | uniq -c

O find . -type f -printf '%f\n' imprime o nome de base de todos os arquivos regulares na árvore, sem diretórios. Isso elimina a necessidade de se preocupar com diretórios que podem ter . neles em seu sed regex.

O sed -r -n 's/.+(\..*)$//p' substitui o nome do arquivo recebido apenas por sua extensão. Por exemplo, .somefile.ext se torna .ext . Observe o .+ inicial na regex; isso resulta em qualquer correspondência que precise de pelo menos um caractere antes do . da extensão. Isso evita que nomes de arquivos como .gitignore sejam tratados como não tendo nenhum nome e a extensão '.gitignore', que é provavelmente o que você deseja. Caso contrário, substitua o .+ por um .* .

O resto da linha é da resposta aceita.

Editar : se você deseja um histograma bem ordenado no formato Pareto chart , apenas adicione outro sort ao final:

find . -type f -printf '%f\n' | sed -r -n 's/.+(\..*)$//p' | sort | uniq -c | sort -bn

Exemplo de saída de uma árvore de código fonte do Linux:

    1 .1992-1997
    1 .1994-2004
    1 .1995-2002
    1 .1996-2002
    1 .ac
    1 .act2000
    1 .AddingFirmware
    1 .AdvancedTopics
    [...]
 1445 .S
 2826 .o
 2919 .cmd
 3531 .txt
19290 .h
23480 .c
    
por 29.10.2016 / 04:11
0

Eu coloquei um script bash na minha pasta ~/bin chamada exhist com este conteúdo:

#!/bin/bash

for d in */ ; do
        echo $d
        find $d -type f | sed -r 's/.*\/([^\/]+)//' | sed 's/^[^\.]*$//' | sed -r 's/.*(\.[^\.]+)$//' | sort | uniq -c | sort -nr
#       files only      | keep filename only          | no ext -> '' ext   | keep part after . (i.e. ext) | count          | sort by count desc
done

Seja qual for o diretório em que estou, apenas digito 'exh', a guia é preenchida automaticamente e vejo algo assim:

$ exhist
src/
      7 .java
      1 .txt
target/
     42 .html
     10 .class
      4 .jar
      3 .lst
      2 
      1 .xml
      1 .txt
      1 .properties
      1 .js
      1 .css

P.S. Cortar a peça após o ponto de interrogação deve ser simples de fazer com outro comando sed provavelmente após o último (eu não tentei): sed 's/\?.*//'

    
por 22.08.2017 / 12:59

Tags