statistiche ricorsive sui tipi di file nella directory?


65

Ho creato un sito web per un progetto di conversione. Vorrei fare alcune statistiche sui tipi di file presenti, ad esempio 400 .htmlfile, 100 .gif, ecc. Qual è un modo semplice per farlo? Deve essere ricorsivo.

Modifica: con lo script pubblicato da maxschelpzig, sto riscontrando alcuni problemi a causa dell'architettura del sito che ho raschiato. Alcuni file hanno il nome *.php?blah=blah&foo=barcon vari argomenti, quindi li considera tutti unici. Quindi la soluzione deve essere considerata *.php*dello stesso tipo, per così dire.

Risposte:


96

È possibile utilizzare finde uniqper questo, ad esempio:

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

Spiegazione del comando

  • find stampa in modo ricorsivo tutti i nomi di file
  • sed elimina da ogni nome file il prefisso fino all'estensione del file
  • uniq presuppone un input ordinato
    • -c fa il conteggio (come un istogramma).

Ho una sceneggiatura simile. Semplice e veloce.
Rufo El Magufo,

Alcuni file hanno il nome *.php?blah=blah&foo=barcon vari argomenti, quindi li considera tutti unici. Come posso modificarlo per cercarlo *.php*?
user394

3
Puoi provare a usare un'espressione sed diversa, ad es.sed 's/^.*\(\.[a-zA-Z0-9][a-zA-Z0-9][a-zA-Z0-9]\).*$/\1/'
maxschlepzig

Grazie per aver dedicato del tempo a spiegare cosa fa ogni porzione. Così tante risposte su argomenti simili saltano questa parte. / learning-to-fish
MechEthan

1
@ bela83, le varianti di potatura si basano sulla valutazione del cortocircuito - quindi, la mia prima versione find -name '.*' -prune -o -type f -printvaluta come: se la voce della directory corrisponde .*quindi potarla, altrimenti se è un file quindi stamparlo. Poiché .*anche le corrispondenze ., ovvero il CWD, tutto viene eliminato, ovvero find non scende nemmeno nella prima directory. Forse, le versioni di 2 anni si sono findcomportate diversamente - o era solo una mia supervisione, allora. Ad ogni modo, find -name '.*' -not -name . -prune -o -type f -printrisolve questo.
maxschlepzig,

6

Con zsh:

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

Il modello **/?*.* corrisponde a tutti i file che hanno un'estensione, nella directory corrente e nelle sue sottodirectory ricorsivamente. Il qualificatore glob D consente di zshattraversare anche le directory nascoste e considera i file nascosti, .seleziona solo i file regolari. Il modificatore di cronologia mantiene solo l'estensione del file. print -rlstampa una corrispondenza per riga. uniq -cconta elementi identici consecutivi (il risultato glob è già ordinato). L'ultima chiamata per sortordinare gli interni in base al conteggio.


5

Questo one-liner sembra essere un metodo abbastanza robusto:

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

Le find . -type f -printf '%f\n'stampe il nome base di ogni file regolare nella struttura, senza directory. Ciò elimina la necessità di preoccuparsi delle directory che potrebbero essere .presenti nella tua sedregex.

Il sed -r -n 's/.+(\..*)$/\1/p'sostituisce il nome del file in arrivo solo con la sua estensione. Ad esempio, .somefile.extdiventa .ext. Nota l'iniziale .+nella regex; ciò si traduce in qualsiasi corrispondenza che richiede almeno un carattere prima dell'estensione .. In questo modo si evita che i nomi di file come .gitignorequelli non abbiano alcun nome e l'estensione ".gitignore", che è probabilmente ciò che si desidera. In caso contrario, sostituisci .+con a .*.

Il resto della riga è dalla risposta accettata.

Modifica : se vuoi un istogramma ben ordinato in formato grafico Pareto , aggiungine un altro sortalla fine:

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

Output di esempio da un albero dei sorgenti Linux incorporato:

    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

1

Ho inserito uno script bash nella mia ~/bincartella chiamata exhistcon questo contenuto:

#!/bin/bash

for d in */ ; do
        echo $d
        find $d -type f | sed -r 's/.*\/([^\/]+)/\1/' | sed 's/^[^\.]*$//' | sed -r 's/.*(\.[^\.]+)$/\1/' | 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

Indipendentemente dalla directory in cui mi trovo, digito semplicemente "exh", la scheda lo completa automaticamente e vedo qualcosa del genere:

$ 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

PS Il taglio della parte dopo il punto interrogativo dovrebbe essere semplice da fare con un altro comando sed probabilmente dopo l'ultimo (non l'ho provato): sed 's/\?.*//'

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.