2009-03-10 7 views
17

Desidero ottenere un elenco di cartelle al livello corrente (escluse le relative sottocartelle) e stampare semplicemente il nome della cartella e un conteggio del numero di file nella cartella (preferibilmente il filtro per * .jpg, se possibile).Comando UNIX per elencare le cartelle con il numero di file

Ciò è possibile nella shell bash standard? ls -l stampe su tutto ma il file contano :)

+2

Per la persona che ha votato vicino: bash è un linguaggio vero e proprio . – Bernard

risposta

21

mi è venuta in mente questa:

find -maxdepth 1 -type d | while read dir; do 
    count=$(find "$dir" -maxdepth 1 -iname \*.jpg | wc -l) 
    echo "$dir ; $count" 
done 

goccia al secondo -maxdepth 1 se la ricerca all'interno di directory per i file jpg dovrebbe essere ricorsiva considerando sottodirectory . Nota che considera solo il nome dei file. Puoi rinominare un file, nascondendo che si tratta di un'immagine jpg. È possibile utilizzare il comando file di fare una supposizione sul contenuto, invece (ora, le ricerche anche in modo ricorsivo):

find -mindepth 1 -maxdepth 1 -type d | while read dir; do 
    count=$(find "$dir" -type f | xargs file -b --mime-type | 
      grep 'image/jpeg' | wc -l) 
    echo "$dir ; $count" 
done 

Tuttavia, che è molto più lento, dal momento che deve leggere parte dei file e, infine, interpretare ciò che contengono (se è fortunato, trova un ID magico all'inizio del file). Lo -mindepth 1 impedisce di stampare . (la directory corrente) come un'altra directory che cerca.

1
#!/bin/bash 
for dir in `find . -type d | grep -v "\.$"`; do 
echo $dir 
ls $dir/*.jpg | wc -l 
done; 
8

il mio è più veloce da digitare dalla riga di comando. :)

gli altri suggerimenti offrono un vantaggio reale rispetto al seguente?

find -name '*.jpg' | wc -l    # recursive 


find -maxdepth 1 -name '*.jpg' | wc -l # current directory only 
+0

esempio: insegnante vuole elencare le immagini jpg dei suoi allievi. quindi mette il comando in/home e vuole elencare tutto il jpg in quelle sub-dir per verificare che non contengano alcune cose *** :) esempio del mio precedente unix-teacher. sapeva di cosa stava parlando: p ppls ha cercato di nascondere il loro pr0n nei file bin: D –

+0

Questo stampa solo il numero totale di file, non il numero per cartella. L'ho fatto ora comunque, seguendo il commento sopra. – DisgruntledGoat

+0

@DisgruntledGoat, ho letto male la tua domanda. Mi dispiace per quello Ora capisco. – m42

1

È possibile farlo senza comandi esterni:

for d in */; do 
    set -- "$d"*.jpg 
    printf "%s: %d\n" "${d%/}" "$#" 
done 

oppure è possibile utilizzare awk (nawk o /usr/XPG4/bin/awk su Solaris):

printf "%s\n" */*jpg | 
    awk -F\/ 'END { 
    for (d in _) 
     print d ":",_[d] 
     } 
    { _[$1]++ }' 
9

Ho trovato questa domanda afte Ho già capito la mia sceneggiatura simile. Sembra adattarsi alle tue condizioni ed è molto flessibile, quindi ho pensato di aggiungerlo come risposta.

Vantaggi:

  • possono essere raggruppati per qualsiasi profondità (0 per ., 1 per sottodirectory di primo livello, etc.)
  • stampe abbastanza uscita
  • alcun loop, e solo uno find di comando, quindi è un po 'più veloce su grandi directory
  • può ancora essere sintonizzati per aggiungere filtri personalizzati (maxdepth per renderlo non ricorsiva, il nome del file modello)

codice prima:

find -P . -type f | rev | cut -d/ -f2- | rev | \ 
     cut -d/ -f1-2 | cut -d/ -f2- | sort | uniq -c 

avvolto in una funzione e ha spiegato:

fc() { 
    # Usage: fc [depth >= 0, default 1] 
    # 1. List all files, not following symlinks. 
    #  (Add filters like -maxdepth 1 or -iname='*.jpg' here.) 
    # 2. Cut off filenames in bulk. Reverse and chop to the 
    #  first/(remove filename). Reverse back. 
    # 3. Cut everything after the specified depth, so that each line 
    #  contains only the relevant directory path 
    # 4. Cut off the preceeding '.' unless that's all there is. 
    # 5. Sort and group to unique lines with count. 

    find -P . -type f \ 
     | rev | cut -d/ -f2- | rev \ 
     | cut -d/ -f1-$((${1:-1}+1)) \ 
     | cut -d/ -f2- \ 
     | sort | uniq -c 
} 

produce un output simile a questo:

$ fc 0 
1668 . 

$ fC# depth of 1 is default 
    6 . 
    3 .ssh 
    11 Desktop 
    44 Downloads 
1054 Music 
550 Pictures 

Naturalmente con il primo numero che può essere convogliato a sort:

$ fc | sort 
    3 .ssh 
    6 . 
    11 Desktop 
    44 Downloads 
550 Pictures 
1054 Music 
+0

Su Solaris non è disponibile 'rev'. Puoi usare 'perl' invece come soluzione universale: ' find -P. -tipo f | perl -lpe '$ _ = reverse' | taglia -d/-f2- | perl -lpe '$ _ = reverse' | taglia -d/-f1-2 | taglia -d/-f2- | ordinare | uniq -c' –