¿Cómo obtener el tamaño real del directorio (fuera de du)?

17

¿Cómo obtengo el tamaño real del directorio, usando las herramientas estándar de UNIX / Linux?

Alternativa pregunta: ¿Cómo llego du mostrarme el tamaño del directorio actual (no el uso del disco)?

Dado que las personas parecen tener diferentes definiciones del término "tamaño": Mi definición de "tamaño de directorio" es la suma de todos los archivos regulares dentro de ese directorio.

NO me importa el tamaño del inodo del directorio o lo que sea (bloques * tamaño de bloque) que los archivos ocupan en el sistema de archivos respectivo. Un directorio con 3 archivos, 1 byte cada uno, tiene un tamaño de directorio de 3 bytes (según mi definición).

Calcular el tamaño del directorio usando du parece no ser confiable.
Por ejemplo, mkdir foo && du -b fooinforma "4096 foo", 4096 bytes en lugar de 0 bytes. Con directorios muy grandes, el tamaño de directorio informado por du -hspuede ser de 100 GB (!) Y más (sistema de archivos comprimido).

Entonces, ¿qué (herramienta / opción) debe usarse para obtener el tamaño real del directorio?

básico6
fuente
¿Qué sistema de archivos se usa en la nueva ubicación? ¿Es xfspor casualidad?
Sergey Vlasov
Y si su nuevo FS es realmente XFS, el uso del disco muy aumentado probablemente se deba a una asignación previa agresiva , lo que disminuye la fragmentación del archivo a costa del uso del disco.
Sergey Vlasov

Respuestas:

8

Aquí hay un script que muestra un tamaño de directorio legible por humanos usando las herramientas estándar de Unix (POSIX).

#!/bin/sh
find ${1:-.} -type f -exec ls -lnq {} \+ | awk '
BEGIN {sum=0} # initialization for clarity and safety
function pp() {
  u="+Ki+Mi+Gi+Ti+Pi+Ei";
  split(u,unit,"+");
  v=sum;
  for(i=1;i<7;i++) {
    if(v<1024) break;
    v/=1024;
  }
  printf("%.3f %sB\n", v, unit[i]);
}
{sum+=$5}
END{pp()}'

p.ej:

$ ds ~        
72.891 GiB
jlliagre
fuente
Y ahora he encontrado otra opción que está ausente en todas las sugeridas lsinvocaciones aquí: -q. Sin esta opción, el script se romperá si algún nombre de archivo contiene caracteres de nueva línea. Escribir scripts de shell realmente confiables es demasiado difícil ...
Sergey Vlasov
@SergeyVlasov El script que publiqué no debería romperse con dichos archivos, solo ignorando las líneas adicionales. El único caso de problema ocurriría si un archivo cuidadosamente elaborado tuviera una línea extra con un quinto colon que contiene un valor numérico. Su sugerencia de hecho evitaría esa situación. Gracias por el consejo, script actualizado.
jlliagre
Excelente respuesta +1 para usted, señor
ehime
Esta es una de las soluciones más confiables. Funciona con nombres de archivo que tienen espacios o comillas e imprime un tamaño legible para humanos.
basic6
@KIAaze ¡Gracias por revisar y corregir mi código!
jlliagre
8

Algunas versiones de dusoportan el argumento --apparent-sizepara mostrar el tamaño aparente en lugar del uso del disco. Entonces su comando sería:

du -hs --apparent-size

Desde las páginas man para du incluidas con Ubuntu 12.04 LTS:

--apparent-size
      print apparent sizes,  rather  than  disk  usage;  although  the
      apparent  size is usually smaller, it may be larger due to holes
      in (`sparse') files, internal  fragmentation,  indirect  blocks,
      and the like
Brian
fuente
1
no funciona: informe algún espacio para directorios vacíos
Karl Forner
1
Esto funcionó para mí.
connorbode
2
Tiene tamaños significativamente diferentes cuando compara directorios en diferentes sistemas de archivos. Por ejemplo, la misma carpeta tiene un tamaño aparente de 290 Gb en el sistema de archivos zfs y 324 Gb de exFat. Las soluciones anteriores dan el mismo tamaño.
Pixus.ru
4

Solo una alternativa, usando ls:

ls -nR | grep -v '^d' | awk '{total += $5} END {print total, "Total"}'

ls -nR: me -ngusta -l, pero enumere UID y GID numéricos y -Renumere subdirectorios de forma recursiva.

grep -v:Invierta el sentido de coincidencia para seleccionar líneas no coincidentes. (-v es especificado por POSIX). '^ d'excluirá los directorios.

Comando Ls: http://linux.about.com/od/commands/l/blcmdl1_ls.htm

Hombre Grep: http://linux.die.net/man/1/grep

EDITAR :

Editado como la sugerencia @ Sergey Vlasov.

stderr
fuente
Usar la -nopción para en lslugar de -l(mostrar números UID / GID en lugar de nombres) es más seguro, porque los nombres de usuarios y grupos pueden contener espacios (por ejemplo, si se usa winbindo sssdse usa para unir el sistema a un dominio de Windows, puede obtener nombres de grupo como domain users) . También debería ser más rápido debido a que no es necesario buscar nombres de usuarios y grupos.
Sergey Vlasov
¡Gracias, esto es MUCHO más rápido que find -exec ls!
gpothier
4

Suponiendo que tiene un dunúcleo de GNU, este comando debe calcular el tamaño aparente total del número arbitrario de archivos regulares dentro de un directorio sin ningún límite arbitrario en el número de archivos:

find . -type f -print0 | du -scb --files0-from=- | tail -n 1

Agregue la -lopción dusi hay algunos archivos enlazados en el interior y desea contar cada enlace por separado (de forma predeterminada, ducuenta con múltiples enlaces duros solo una vez).

La diferencia más importante con plain du -sbes que recursivo dutambién cuenta los tamaños de los directorios, que los diferentes sistemas de archivos informan de manera diferente; para evitar esto, el findcomando se usa para pasar solo archivos regulares a du. Otra diferencia es que los enlaces simbólicos se ignoran (si se deben contar, se finddebe ajustar el comando).

Este comando también consumirá más memoria que la simple du -sb, porque usar el dispositivo de almacenamiento de --files0-from=FILEmarcas duy los números de inodo de todos los archivos procesados, en oposición al comportamiento predeterminado de recordar solo archivos con más de un enlace duro. (Esto no es un problema si la -lopción se usa para contar los enlaces duros varias veces, porque la única razón para almacenar los números de dispositivo e inodo es omitir los archivos enlazados que ya se han procesado).

Si desea obtener una representación del tamaño total legible por humanos, simplemente agregue la -hopción (esto funciona porque duse invoca solo una vez y calcula el tamaño total en sí, a diferencia de otras respuestas sugeridas):

find . -type f -print0 | du -scbh --files0-from=- | tail -n 1

o (si le preocupa que algunos de los efectos -bsean anulados -h)

find . -type f -print0 | du -sc --apparent-size -h --files0-from=- | tail -n 1
Sergey Vlasov
fuente
No estoy seguro de qué hacer para FreeBSD, aunque -bprobablemente no se pueda reemplazar por -A -B 1, no hay un equivalente para ello --files0-from=-, y el uso xargsnecesitará algunas soluciones en caso de que la lista de archivos sea mayor que ARG_MAX(y alguna solución externa para resultados legibles por humanos).
Sergey Vlasov
3

Si todo lo que desea es el tamaño de los archivos, excluyendo el espacio que ocupan los directorios, puede hacer algo como

find . -type f -print0 | xargs -0 du -scb | tail -n 1

@SergeyVlasov señaló que esto fallará si tiene más archivos que argmax. Para evitar eso, puede usar algo como:

find . -type f -exec du -sb '{}' \; | gawk '{k+=$1}END{print k}'
terdon
fuente
1
Este comando silenciosamente dará un resultado incorrecto si el directorio contiene tantos archivos que no caben en el límite del tamaño de los argumentos execve (), en este caso xargsinvocará duvarias veces, y cada invocación imprimirá el total general solo por su parte de la lista completa de archivos, luego tailmostrará solo el tamaño total de la última parte.
Sergey Vlasov
1
@SergeyVlasov buen punto, no había pensado en eso, gracias, respuesta actualizada.
terdon