Comando UNIX per elencare le cartelle con il numero di file
Domanda
Voglio ottenere un elenco di cartelle al livello corrente (senza includere le loro sottocartelle) e semplicemente stampare il nome della cartella e un conteggio del numero di file nella cartella (preferibilmente filtrando su * .jpg se possibile).
È possibile nella shell bash standard? ls -l
stampa su tutto tranne il conteggio dei file :)
Soluzione
Ho pensato a questo:
find -maxdepth 1 -type d | while read dir; do
count=$(find "$dir" -maxdepth 1 -iname \*.jpg | wc -l)
echo "$dir ; $count"
done
Rilascia il secondo -maxdepth 1
se la ricerca all'interno delle directory dei file jpg deve essere ricorsiva considerando le sottodirectory. Si noti che questo considera solo il nome dei file. È possibile rinominare un file, nascondendo che si tratta di un'immagine jpg. Puoi invece usare il comando file
per fare un'ipotesi sul contenuto (ora, cerca 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, è molto più lento, poiché deve leggere parte dei file ed eventualmente interpretare ciò che contengono (se è fortunato, trova un id magico all'inizio del file). -mindepth 1
impedisce di stampare .
(la directory corrente) come un'altra directory che cerca.
Altri suggerimenti
Ho trovato questa domanda dopo aver già capito il mio script simile. Sembra adattarsi alle tue condizioni ed è molto flessibile, quindi ho pensato di aggiungerlo come risposta.
Vantaggi:
- può essere raggruppato in qualsiasi profondità (0 per
.
, 1 per sottodirectory di primo livello, ecc.) - stampa un output grazioso
- nessun loop e solo un comando
find
, quindi è un po 'più veloce su directory di grandi dimensioni - può ancora essere ottimizzato per aggiungere filtri personalizzati (maxdepth per renderlo non ricorsivo, modello di nome file)
Codice non elaborato:
find -P . -type f | rev | cut -d/ -f2- | rev | \
cut -d/ -f1-2 | cut -d/ -f2- | sort | uniq -c
Avvolto in una funzione e 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 output in questo modo:
$ fc 0
1668 .
$ fc # depth of 1 is default
6 .
3 .ssh
11 Desktop
44 Downloads
1054 Music
550 Pictures
Ovviamente con il numero prima può essere reindirizzato a sort
:
$ fc | sort
3 .ssh
6 .
11 Desktop
44 Downloads
550 Pictures
1054 Music
il mio è più veloce da digitare dalla riga di comando. :)
gli altri suggerimenti offrono qualche vantaggio reale rispetto ai seguenti?
find -name '*.jpg' | wc -l # recursive
find -maxdepth 1 -name '*.jpg' | wc -l # current directory only
#!/bin/bash
for dir in `find . -type d | grep -v "\.<*>quot;`; do
echo $dir
ls $dir/*.jpg | wc -l
done;
Puoi farlo senza comandi esterni:
for d in */; do
set -- "$d"*.jpg
printf "%s: %d\n" "${d%/}" "$#"
done
Oppure puoi usare awk ( nawk o / usr / xpg4 / bin / awk su Solaris ) :
printf "%s\n" */*jpg |
awk -F\/ 'END {
for (d in _)
print d ":",_[d]
}
{ _[$1]++ }'