Me gustaría encontrar el archivo más grande en cada directorio de forma recursiva

Me gustaría encontrar el archivo más grande en cada directorio de forma recursiva

El resultado incluiría el nombre del directorio, el nombre del archivo y el tamaño del archivo. Uno (archivo más grande) para cada directorio desde donde se ejecuta el comando.

Si es posible, también el tamaño promedio de los archivos en ese directorio.

El propósito es buscar en los directorios archivos que sean mucho más grandes que los demás en el directorio para poder reemplazarlos.

Respuesta1

Con GNU findy sort( sed4.2.2 o superior), ordene una vez por tamaño de archivo y otra vez por ruta de directorio:

find /some/dir -type f -printf '%s %f%h\0' | 
  sort -zrn |
  sort -zut/ -k2 |
  sed -zre 's: ([^/]*)(/.*): \2/\1:'

Explicación:

  • Se imprimen el tamaño del archivo, el nombre y la ruta (el primero separado por un espacio y los dos siguientes separados por /), y cada entrada termina con el carácter ASCII NUL.
  • Luego ordenamos numéricamente usando el tamaño, asumiendo una salida delimitada por NUL (y en orden inverso, por lo que los archivos más grandes primero).
  • Luego usamos sortpara imprimir solo las primeras entradas únicas usando todo lo del segundo /campo separado, que sería la ruta al directorio que contiene el archivo.
  • Luego usamos sedpara intercambiar el directorio y los nombres de archivos, de modo que obtengamos una ruta normal.

Para obtener resultados legibles, reemplace ASCII NUL con nuevas líneas:

find /some/dir -type f -printf '%s %f%h\0' | 
  sort -zrn |
  sort -zut/ -k2 |
  sed -zre 's: ([^/]*)(/.*): \2/\1:' |
  tr '\0' '\n'

Salida de ejemplo:

$ find /var/log -type f -printf '%s %f%h\0' | sort -zrn | sort -zt/ -uk2 | sed -zre 's: ([^/]*)(/.*): \2/\1:' | tr '\0' '\n'
3090885 /var/log/syslog.1
39789 /var/log/apt/term.log
3968 /var/log/cups/access_log.1
31 /var/log/fsck/checkroot
467020 /var/log/installer/initial-status.gz
44636 /var/log/lightdm/seat0-greeter.log
15149 /var/log/lxd/lxd.log
4932 /var/log/snort/snort.log
3232 /var/log/unattended-upgrades/unattended-upgrades-dpkg.log

Respuesta2

Combinando findy awkpermite calcular también los promedios:

find . -type f -printf '%s %h/%f\0'|awk 'BEGIN { RS="\0" } { SIZE=$1; for (i = 1; i <= NF - 1; i++) $i = $(i + 1); NF = NF - 1; DIR=$0; gsub("/[^/]+$", "", DIR); FILE=substr($0, length(DIR) + 2); SUMSIZES[DIR] += SIZE; NBFILES[DIR]++; if (SIZE > MAXSIZE[DIR] || !BIGGESTFILE[DIR]) { MAXSIZE[DIR] = SIZE; BIGGESTFILE[DIR] = FILE } }; END { for (DIR in SUMSIZES) { printf "%s: average %f, biggest file %s %d\n", DIR, SUMSIZES[DIR] / NBFILES[DIR], BIGGESTFILE[DIR], MAXSIZE[DIR] } }'

Presentado de una manera más legible, el script AWK es

BEGIN { RS="\0" }

{
  SIZE=$1
  for (i = 1; i <= NF - 1; i++) $i = $(i + 1)
  NF = NF - 1
  DIR=$0
  gsub("/[^/]+$", "", DIR)
  FILE=substr($0, length(DIR) + 2)
  SUMSIZES[DIR] += SIZE
  NBFILES[DIR]++
  if (SIZE > MAXSIZE[DIR] || !BIGGESTFILE[DIR]) {
    MAXSIZE[DIR] = SIZE
    BIGGESTFILE[DIR] = FILE
  }
}

END {
  for (DIR in SUMSIZES) {
    printf "%s: average %f, biggest file %s %d\n", DIR, SUMSIZES[DIR] / NBFILES[DIR], BIGGESTFILE[DIR], MAXSIZE[DIR]
  }
}

Esto espera registros de entrada separados por nulos (lo robé dela respuesta de muru); para cada registro de entrada,

  • almacena el tamaño (para uso posterior),
  • elimina todo lo que está antes del primer carácter en la ruta (para que al menos manejemos correctamente los nombres de archivos con espacios),
  • extrae el directorio,
  • extrae el nombre del archivo,
  • agrega el tamaño que almacenamos anteriormente a la suma de tamaños en el directorio,
  • incrementa el número de archivos en el directorio (para que podamos calcular el promedio),
  • si el tamaño es mayor que el tamaño máximo almacenado para el directorio, o si aún no hemos visto un archivo en el directorio, actualiza la información del archivo más grande.

Una vez hecho todo esto, el script recorre las claves SUMSIZESy genera el directorio, el tamaño promedio, el nombre y el tamaño del archivo más grande.

Puede canalizar la salida sortpara ordenarla por nombre de directorio. Si desea formatear adicionalmente los tamaños en una forma amigable para los humanos, puede cambiar la printflínea a

printf "%.2f %d %s: %s\n", SUMSIZES[DIR] / NBFILES[DIR], MAXSIZE[DIR], DIR, BIGGESTFILE[DIR]

y luego canalice la salida a numfmt --field=1,2 --to=iec. Aún puedes ordenar el resultado por nombre de directorio, solo necesitas ordenar comenzando con el tercer campo: sort -k3.

Respuesta3

Zsh'spatrones comodínSería muy útil para el tipo de cosas que estás haciendo. Específicamente, zsh puede hacer coincidir archivos por atributos como tipo, tamaño, etc. a través declasificatorios globales. Los clasificatorios globales también permiten ordenar los partidos.

Por ejemplo, en zsh, *(.DOLN[1])se expande al nombre del archivo más grande en el directorio actual. *es el patrón para el nombre del archivo (coincide con todo, excepto posiblemente con archivos de puntos dependiendo de las opciones del shell). El calificador .restringe las coincidencias a archivos normales, Dhace que *se incluyan archivos de puntos, OLordena por tamaño decreciente (“longitud”), Nhace que la expansión esté vacía si no hay ningún archivo coincidente y [1]selecciona solo la primera coincidencia.

Puede enumerar directorios de forma recursiva con **/. Por ejemplo, el siguiente bucle itera sobre todos los subdirectorios del directorio actual y sus subdirectorios de forma recursiva:

for d in **/*(/); do … done

Puedes usarzstatpara acceder al tamaño de un archivo y otros metadatos sin tener que depender de otras herramientas para el análisis.

zmodload -F zsh/stat b:zstat
files=(*(DNoL))
zstat -A sizes +size -- $files
total=0; for s in $sizes; do total+=$s; done
if ((#sizes > 0)); then
  max=$sizes[-1]
  average=$((total/#sizes))
  median=$sizes[$((#sizes/2))]
fi

Respuesta4

Considere el uso de baobab o algún software similar, y es probable que uno o más de ellos estén incluidos en su distribución. Visualizan muy bien los directorios de problemas.

  • Baobab
  • Informe JDisk
  • ncdu
  • K4DirStat
  • QDirEstat
  • Mapa de GD

http://alternativeto.net/software/baobab/?platform=linux

Y la página de manual de baobab dice cómo es.

$> man baobab
BAOBAB(1)

NAME
       Baobab - A graphical tool to analyse disk usage

SYNOPSIS
       baobab  [directory]

DESCRIPTION
       baobab is able to scan either specific folders or the whole filesys-
       tem (local and remote), in order to give the user a graphical tree
       representation including each directory size or percentage in the
       branch.  It also auto-detects in real-time any change made to your
       home directory as far as any mounted/unmounted device. A graphical
       treemap window is also provided for any selected folder.

       A detailed documentation on the program could be read at:
       http://www.gnome.org/projects/baobab

AUTHOR
       Fabio MARZOCCA <[email protected]>



                                                                     BAOBAB(1)

información relacionada