Conteggio dei file in ogni sottodirectory


21

Vorrei un comando BASH per elencare solo il conteggio dei file in ogni sottodirectory di una directory.

Ad esempio, nella directory /tmpci sono dir1, dir2, ... mi piacerebbe vedere:

`dir1` : x files 
`dir2` : x files ...

Risposte:


32

Supponendo che si desideri solo un conteggio ricorsivo di file, non di directory e altri tipi, qualcosa del genere dovrebbe funzionare:

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

Inoltre, ottengo "find: warning: hai specificato l'opzione -maxdepth dopo un argomento non -type -type, ma le opzioni non sono posizionali (-maxdepth influenza i test specificati prima e quelli specificati dopo). Specifica le opzioni prima di altri argomenti. "
jldupont,

2
Entrambe le risposte fornite finora daranno risultati errati nel caso improbabile che ci siano file i cui nomi includono caratteri di nuova riga. Puoi gestirlo con un find... -print0 | xargs -0....
Scott,

@jldupont: sposta gli argomenti di profondità prima del tipo "d", ho modificato la risposta.
Thor,

Sì, e lasciatemi aggiungere le informazioni che questa eccellente soluzione non prenderà alcuna variabile esterna e quindi funzionerà con bash alias!!
syntaxerror,

veloce e tubazioni sort -rn -k 2,2 -t$':'ottieni l'elenco DESC
Andre Figueiredo,

14

Questo compito mi ha affascinato così tanto che volevo trovare una soluzione da solo. Non ci vuole nemmeno un po 'di loop e può essere più veloce nella velocità di esecuzione. Inutile dire che gli sforzi di Thor mi hanno aiutato molto a capire le cose in dettaglio.

Quindi ecco il mio:

find . -maxdepth 1 -mindepth 1 -type d -exec sh -c 'echo "{} : $(find "{}" -type f | wc -l)" file\(s\)' \;

Sembra modesto per un motivo, perché è molto più potente di quanto sembri. :-)

Tuttavia, se hai intenzione di includerlo nel tuo .bash_aliasesfile, deve essere simile al seguente:

alias somealias='find . -maxdepth 1 -mindepth 1 -type d -exec sh -c '\''echo "{} : $(find "{}" -type f | wc -l)" file\(s\)'\'' \;'

Nota la gestione molto delicata delle virgolette singole nidificate . E no, non è non è possibile usare le virgolette per l' sh -cargomento.


È più lento poiché invoca / bin / sh per ogni directory. Puoi verificarlo con strace -fc script. La tua versione effettua circa il 70% in più di chiamate di sistema. +1 per il codice più breve :-)
Thor

1
ispirato da questo; ordinati per numero di file:find . -maxdepth 1 -mindepth 1 -type d -exec sh -c 'echo "$(find "{}" -type f | wc -l)" {}' \; | sort -nr
mnagel

7
find . -type f | cut -d"/" -f2 | uniq -c

Elenca una cartella e file nella cartella corrente con un conteggio dei file trovati sotto. IMO rapido e utile. (i file vengono visualizzati con il conteggio 1).


1
Che ne dici di una piccola spiegazione di come funziona? :)
C0deDedalo

1
fantastico, grazie! Potresti voler aggiungere | sort -rnper ordinare i sottodiretti per numero di file.
Dennis Golomazov,

1

L'uso di find è sicuramente la strada da percorrere se si desidera contare in modo ricorsivo, ma se si desidera solo un conteggio dei file direttamente in una determinata directory:

ls dir1 | wc -l


Non voglio farlo per ognuna delle migliaia di directory che ho lì ...
jldupont

Quindi usa xargs. ls -d */ | xargs -n1 ls | wc -l(Usa la risposta che hai accettato se funziona già, però! Questo è giusto e ora lo sai.)
jrajav

la tua proposta non ha mostrato alcun risultato in molti secondi mentre la risposta che ho accettato ha fatto.
jldupont,

@jrajav questo approccio fallisce assolutamente per le directory che contengono spazi bianchi. Questo è il motivo findper cui è così importante. (figuriamoci -print0e xargs -0, già indicato da Scott nell'altra risposta)
syntaxerror il

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

Ho spesso bisogno di contare il numero di file nelle mie sottodirectory e usare questo comando. Preferisco che il conteggio appaia per primo.


0

Quello che uso ... Questo crea una matrice di tutte le sottodirectory in quella che dai come parametro. Stampa la sottodirectory e il conteggio della stessa sottodirectory fino a quando non vengono elaborate tutte le sottodirectory.

#!/bin/bash    
directories=($(/bin/ls -l $1 | /bin/grep "^d" | /usr/bin/awk -F" " '{print $9}'))

for item in ${directories[*]}
    do
        if [ -d "$1$item" ]; then
            echo "$1$item"
            /bin/ls $1$item | /usr/bin/wc -l
        fi
    done

0

Puoi usare questo codice Python. Avviare l'interprete eseguendo python3e incollando questo:

folder_path = '.'
import os, glob
for folder in sorted(glob.glob('{}/*'.format(folder_path))):
    print('{:}: {:>8,}'.format(os.path.split(folder)[-1], len(glob.glob('{}/*'.format(folder)))))

O una versione ricorsiva per i conteggi nidificati:

import os, glob
def nested_count(folder_path, level=0):
    for folder in sorted(glob.glob('{}/'.format(os.path.join(folder_path, '*')))):
        print('{:}{:}: {:,}'.format('    '*level, os.path.split(os.path.split(folder)[-2])[-1], len(glob.glob(os.path.join(folder, '*')))))
        nested_count(folder, level+1)
nested_count('.')

Esempio di output:

>>> figures: 5
>>> misc: 1
>>> notebooks: 5
>>>     archive: 65
>>>     html: 12
>>>     py: 12
>>>     src: 14
>>> reports: 1
>>>     content: 6
>>> src: 1
>>>     html_download: 1
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.