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 :)

È stato utile?

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]++ }'
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top