Pregunta

Deseo obtener una lista de carpetas en el nivel actual (sin incluir sus subcarpetas) y simplemente imprimir el nombre de la carpeta y un recuento del número de archivos en la carpeta (preferiblemente filtrando a * .jpg si es posible).

¿Es esto posible en el shell bash estándar? ls -l imprime sobre todo menos el recuento de archivos :)

¿Fue útil?

Solución

Se me ocurrió este:

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

Descarte el segundo -maxdepth 1 si la búsqueda en los directorios de archivos jpg debe ser recursiva teniendo en cuenta los subdirectorios. Tenga en cuenta que eso solo considera el nombre de los archivos. Puede cambiar el nombre de un archivo, ocultando que es una imagen jpg. En su lugar, puede usar el comando file para adivinar el contenido (ahora, también busca de forma recursiva):

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

Sin embargo, eso es mucho más lento, ya que tiene que leer parte de los archivos y eventualmente interpretar lo que contienen (si tiene suerte, encuentra una identificación mágica al comienzo del archivo). El -mindepth 1 evita que imprima . (el directorio actual) como otro directorio que busca.

Otros consejos

Encontré esta pregunta después de haber descubierto mi propio script similar. Parece ajustarse a sus condiciones y es muy flexible, así que pensé en agregarlo como respuesta.

Ventajas :

  • se puede agrupar a cualquier profundidad (0 para . , 1 para subdirectorios de primer nivel, etc.)
  • imprime una salida bonita
  • sin bucle, y solo un comando find , por lo que es un poco más rápido en directorios grandes
  • todavía se puede ajustar para agregar filtros personalizados (profundidad máxima para que no sea recursivo, patrón de nombre de archivo)

Código sin formato:

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

Envuelto en una función y explicado:

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 resultados como este:

$ fc 0
1668 .

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

Por supuesto, con el número primero se puede canalizar a sort :

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

el mío es más rápido de escribir desde la línea de comando. :)

¿las otras sugerencias ofrecen alguna ventaja real sobre las siguientes?

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;

Puede hacerlo sin comandos externos:

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

O puede usar awk ( nawk o / usr / xpg4 / bin / awk en Solaris ) :

printf "%s\n" */*jpg |
  awk -F\/ 'END { 
    for (d in _) 
      print d ":",_[d] 
      }
  { _[$1]++ }'
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top