Come posso contare tutti i file in modo ricorsivo attraverso le directory


48

Voglio vedere quanti file sono nelle sottodirectory per scoprire dove si trova tutto l'utilizzo dell'inode sul sistema. Un po 'come farei per l'uso dello spazio

du -sh /*

che mi darà lo spazio utilizzato nelle directory al di fuori di root, ma in questo caso voglio il numero di file, non la dimensione.



Penso che "quanti file siano nelle sottodirectory delle sottodirectory" è una costruzione confusa. Se dichiari più chiaramente ciò che desideri, potresti ottenere una risposta adatta al conto.
Steven D,

@Steven sentiti libero di riscriverlo ... Ho pensato che il mio esempio du -sh /*rendesse abbastanza chiaro come volevo che il conteggio funzionasse. stessa cosa, basta contare i file e non i byte.
xenoterracide,

Mentre menzioni l'utilizzo degli inode, non capisco se si desidera contare il numero di file o il numero di inode utilizzati. I due sono diversi quando sono presenti hard link nel filesystem. La maggior parte, se non tutte, le risposte danno il numero di file. Non utilizzarli su un disco di backup di Apple Time Machine.
mouviciel,

@mouviciel questo non viene utilizzato su un disco di backup, e sì suppongo che potrebbero essere diversi, ma nell'ambiente in cui ci sono ci sono pochissimi hardlink, tecnicamente ho solo bisogno di provarlo. capire dove qualcuno sta bruciando là inode quota.
xenoterracide,

Risposte:


61
find -maxdepth 1 -type d | while read -r dir; do printf "%s:\t" "$dir"; find "$dir" -type f | wc -l; done

Grazie a Gilles e xenoterracide per le correzioni di sicurezza / compatibilità.

La prima parte: find -maxdepth 1 -type drestituirà un elenco di tutte le directory nella directory di lavoro corrente. Questo è indirizzato a ...

La seconda parte: while read -r dir; doinizia un ciclo while - fintanto che la pipe che entra nel while è aperta (che è fino a quando non viene inviato l'intero elenco di directory), il comando read inserirà la riga successiva nella variabile "dir". Quindi continua ...

La terza parte: printf "%s:\t" "$dir";stamperà la stringa in "$ dir" (che contiene uno dei nomi di directory) seguito da una scheda.

La quarta parte: find "$dir -f file"crea un elenco di tutti i file all'interno del nome della directory contenuti in "$ dir". Questo elenco viene inviato a ..

La quinta parte: wc -l;conta il numero di righe che vengono inviate al suo input standard.

La parte finale: donetermina semplicemente il ciclo while.

Quindi otteniamo un elenco di tutte le directory nella directory corrente. Per ognuna di quelle directory, generiamo un elenco di tutti i file in essa contenuti in modo da poterli contare tutti usando wc -l. Il risultato sarà simile a:

./dir1: 234
./dir2: 11
./dir3: 2199
...

Usare sempre read -rcome semplici readbarre rovesciate speciali. Quindi di echo -en "$dir:\t"nuovo rovescerà le barre rovesciate; una soluzione semplice è printf '%s:\t' "$dir"invece utilizzare . Successivamente, $dirdovrebbe essere "$dir"( utilizzare sempre virgolette doppie attorno alle sostituzioni variabili ).
Gilles 'SO- smetti di essere malvagio' il

modificato per suggerimenti @Gilesfind -maxdepth 1 -type d | while read -r dir; do printf "%s:\t" "$dir"; find "$dir" | wc -l; done
xenoterracide

2
Sto aggiungendo sort -n -r -k2alla fine di questo, per molte directory, in modo da sapere dove si trova più utilizzo
xenoterracide

La quarta parte: find "$ dir" crea un elenco di tutti i file all'interno del nome della directory contenuti in "$ dir". Hai dimenticato di aggiungere -type fper farlo elencare i file:find -maxdepth 1 -type d | while read -r dir; do printf "%s:\t" "$dir"; find "$dir" -type f | wc -l; done
Krzysztof Boduch,

1
Non riesco a farlo funzionare su macOS Sierra 10.12.5. illegal option -- mnel findcomando. L'ho cambiato find . -maxdepth ...e l'ho fatto funzionare.
Jeff,

15

Prova find . -type f | wc -l, conterà tutti i file nella directory corrente e tutti i file nelle sottodirectory. Si noti che tutte le directory non verranno conteggiate come file, ma solo i file ordinari.


13

Ecco una raccolta di alcuni utili comandi di elenco (rielaborati in base al codice degli utenti precedenti):

Elenca le cartelle con il conteggio dei file:

find -maxdepth 1 -type d | sort | while read -r dir; do n=$(find "$dir" -type f | wc -l); printf "%4d : %s\n" $n "$dir"; done

Elenca le cartelle con un numero di file diverso da zero:

find -maxdepth 1 -type d | sort | while read -r dir; do n=$(find "$dir" -type f | wc -l); if [ $n -gt 0 ]; then printf "%4d : %s\n" $n "$dir"; fi; done

Elenca le cartelle con il conteggio delle sottocartelle:

find -maxdepth 1 -type d | sort | while read -r dir; do n=$(find "$dir" -type d | wc -l); let n--; printf "%4d : %s\n" $n "$dir"; done

Elenca le cartelle con un conteggio di sottocartelle diverso da zero:

find -maxdepth 1 -type d | sort | while read -r dir; do n=$(find "$dir" -type d | wc -l); let n--; if [ $n -gt 0 ]; then printf "%4d : %s\n" $n "$dir"; fi; done

Elenca cartelle vuote:

find -maxdepth 1 -type d | sort | while read -r dir; do n=$(find "$dir" | wc -l); let n--; if [ $n -eq 0 ]; then printf "%4d : %s\n" $n "$dir"; fi; done

Elenca le cartelle non vuote con il conteggio dei contenuti:

find -maxdepth 1 -type d | sort | while read -r dir; do n=$(find "$dir" | wc -l); let n--; if [ $n -gt 0 ]; then printf "%4d : %s\n" $n "$dir"; fi; done

E btw .. se si desidera che l'output di uno di questi comandi dell'elenco sia ordinato in base al conteggio degli elementi ... eseguire il pipe del comando in un ordinamento: "a-list-command" | sort -n
DolphinDream

12

Provare:

find /path/to/start/at -type f -print | wc -l

come punto di partenza o se si desidera veramente solo ricorrere alle sottodirectory di una directory (e saltare i file in quella directory di livello superiore)

find `find /path/to/start/at -mindepth 1 -maxdepth 1 -type d -print` -type f -print | wc -l

+1 per qualcosa | wc -l ... il conteggio delle parole è un piccolo strumento così carino
Johan

sì, ma questo fa solo 1 directory .... Mi piacerebbe ottenere il conteggio di tutte le directory in una directory, e non voglio eseguirlo separatamente ogni volta ... ovviamente suppongo che potrei usare un ciclo ... ma sono pigro.
xenoterracide,

findfunziona ricorsivamente attraverso tutte le sottodirectory per impostazione predefinita. Se vuoi che funzioni in più posizioni, puoi specificarle tutte tra finde -type.
Didier Trosset,

quella seconda sicuramente non funziona .... l'ho provata su / home. Ho capito 698035 . Dovrei vedere circa 6 numeri.
xenoterracide,

Funziona per me - sei sicuro di avere solo 6 file sotto /home? Sarei sicuro al 100% che tu non lo faccia.
Cry Havok,

4

La seguente soluzione conta il numero effettivo di inode utilizzati a partire dalla directory corrente:

find . -print0 | xargs -0 -n 1 ls -id | cut -d' ' -f1 | sort -u | wc -l

Per ottenere il numero di file dello stesso sottoinsieme, utilizzare:

find . | wc -l

Per soluzioni che esplorano solo le sottodirectory, senza tenere conto dei file nella directory corrente, è possibile fare riferimento ad altre risposte.


1
Buona idea prendendo in considerazione i collegamenti reali. Supponendo GNU trovare, non è necessario tanti passi: find -printf '%i\n' | sort -u | wc -l. Se volessi essere portatile, avresti find . -exec ls -id {} + | cut …invece bisogno .
Gilles 'SO- smetti di essere malvagio' il

2

OS X 10.6 soffoca il comando nella risposta accettata, perché non specifica un percorso per find. Invece usa:

find . -maxdepth 1 -type d | while read -r dir; do printf "%s:\t" "$dir"; find "$dir" -type f | wc -l; done

2

So di essere in ritardo alla festa, ma credo che questa soluzione pura bash(o altra shell che accetta il doppio globo stellare) potrebbe essere molto più veloce in alcune situazioni:

shopt -s globstar    # to enable ** glob in bash
for dir in */; do a=( "$dir"/**/* ); printf "%s\t%s\n" "$dir:" "${#a[*]}"; done

produzione:

d1/:    302
d2/:    24
d3/:    640
...

1

Prova questo:

find -type d -print0 | xargs -0 -I {} sh -c 'printf "%s\t%s\n" "$(find "{}" -maxdepth 1 -type f | wc -l)" "{}"'

Dovrebbe funzionare bene a meno che i nomi dei file includano le nuove righe.


troppo ricorsivo ... Voglio solo vedere il livello più alto, dove totalizza tutto quello che c'è sotto. totalizzato ... questo finisce per stampare ogni directory.
xenoterracide,

@xenoterracide: prova ad aggiungere -maxdepth 1subito dopo il primo find. Se vuoi includere il numero di sottodirectory nel tuo conteggio, rimuovile -type falla fine (che dovrebbe essere stato ! -type dcomunque, in modo che tutti i file non di directory siano stati inclusi).
Dennis Williamson,

1

Se hai ncduinstallato (un must-have quando vuoi fare un po 'di pulizia), digita semplicemente c"Attiva / disattiva la visualizzazione dei conteggi degli elementi figlio". E Ca "Ordina per elementi".


1
lol, questa deve essere la risposta più accettata :)
x-yuri

0

du --inodes

Non sono sicuro del motivo per cui nessuno (me compreso) era a conoscenza di:

du --inodes
--inodes
      list inode usage information instead of block usage

Sono abbastanza sicuro che questo risolva il problema del PO. Ho iniziato a usarlo molto per scoprire dove si trova tutta la spazzatura nelle mie enormi unità (e scaricarla su un disco più vecchio).

Ulteriori informazioni

Se NON vuoi ricorrere (che può essere utile in altre situazioni), aggiungi

-S, --separate-dirs
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.