¿Cómo `du` solo el espacio utilizado por los archivos que no están vinculados en otro lugar?


14

Utilizando las rsync --link-destinstantáneas que ahorran espacio , ¿cómo puedo calcular cuánto espacio ahorré realmente? O más general:

¿Cómo calcular cuánto espacio utiliza un directorio considerando solo los archivos que no están enlazados en otro lugar fuera de la estructura del directorio? Preguntado de manera diferente: ¿Cuánto espacio se liberaría realmente después de eliminar ese directorio? ( du -hsmentiría. Se puede incluir el espacio requerido para los enlaces rígidos)


2
De forma predeterminada, GNU dusolo cuenta los tamaños de archivo una vez, incluso si están vinculados, a menos que use la opción -l/ --count-links. Se ejecuta duen todo el árbol dos veces, con y sin esa opción y la diferencia entre los tamaños debería ser cuánto espacio ha guardado en todos los directorios.
jw013

Respuestas:


9

Suponiendo que no hay enlaces internos (es decir, cada archivo con más de 1 enlace está vinculado desde fuera del árbol), puede hacer lo siguiente:

find . -links -2 -print0 | du -c --files0-from=-

EDITAR Y aquí está lo que bosquejé en el comentario, aplicado. Solo sin du; Felicitaciones a @StephaneChazelas por notar duque no es necesario. Explicación al final.

( find . -type d -printf '%k + ' ; \
  find . \! -type d -printf '%n\t%i\t%k\n' | \
    sort | uniq -c                         | \
    awk '$1 >= $2 { print $4 " +\\" }' ; \
  echo 0 ) | bc

Lo que hacemos es crear una cadena con el uso del disco (en KB) de cada archivo relevante, separados por signos más. Luego alimentamos esa gran adición a bc.

La primera findinvocación hace eso para los directorios.

El segundo findimprime recuento de enlaces, inodo y uso de disco. Pasamos esa lista sort | uniq -cpara obtener una lista de (número de apariciones en el árbol, recuento de enlaces, inodo, uso del disco).

Pasamos esa lista awky, si el primer campo (# de apariencias) es mayor o igual que el segundo (# de enlaces duros), lo que significa que no hay enlaces a este archivo desde fuera del árbol, imprima el cuarto campo ( uso del disco) con un signo más y una barra invertida adjunta.

Finalmente, sacamos a 0, por lo que la fórmula es sintácticamente correcta (de lo +contrario sería en ) y se la pasa a bc. Uf.

(Pero usaría el primer método más simple, si da una respuesta lo suficientemente buena).


Gracias, sí, si ese requisito se cumple, funciona. ¿Pero y si no lo es?
Tobias Kienzler

Eso no funciona ya que no tiene en cuenta el tamaño de los directorios en sí (que generalmente tienen al menos 2 enlaces, y si no lo hicieran, los archivos se contarían dos veces).
Stéphane Chazelas

1
Entonces sería necesario usar findpara imprimir una lista de todos los archivos con sus inodos y conteo de enlaces; luego alguna combinación de sort | uniq -cpara obtener cuántas veces cada inodo aparece en el árbol, luego filtrar aquellos con un recuento de enlaces mayor que el número de apariciones ... y luego alimentar esa lista du. Pero si se cumple el requisito, mejor ahorre el esfuerzo.
angus

@StephaneChazelas Funciona, pero es cierto que no tiene en cuenta el tamaño propio de los directorios. Si solo dutuviera un -dparámetro similar a ls's ...
angus

También tenga en cuenta que en los btrfssistemas de archivos, el número de enlaces para directorios es siempre 1, por lo que deberá agregar un! -type d
Stéphane Chazelas

5

Básicamente, necesita obtener los números de inodo y el número de enlaces para todos los archivos (no directorios), comparar ese número de enlace con el número de ocurrencia de cada inodo y, si difieren, excluir el archivo.

Suponiendo que todos están en el mismo sistema de archivos, algo como esto debería funcionar (con GNU find):

find . -type d -printf '%k\n' -o -printf '%i %n %k\n' |
   awk '
     NF==1{t+=$0; next}
     {n1[$1]=$2; n2[$1]++; s[$1]=$3}
     END {
       for (i in n1)
         if (n1[i] == n2[i])
           t+=s[i]
       print t
     }'

Sí, lo que dije (gracias por el crédito). Pero la precisión adicional que obtienes contando directorios, la pierdes al agregar un uso inexacto del disco.
angus

@angus, ¿qué quieres decir con "uso inexacto del disco"?
Stéphane Chazelas

Nada, estaba totalmente equivocado acerca de lo que %kinformó. ¡Eso es genial, duno es necesario en absoluto! Actualizaré mi respuesta cuando llegue a casa. ¡Gracias!
angus

3

du en realidad no mentirá;) Analiza los directorios que se le dan, contando solo el primero de todos los enlaces duros que apuntan al mismo inodo que encuentra.

Si pregunta duqué ve solo en un directorio, no le importa que haya otros enlaces duros que apunten a los mismos contenidos:

$ du -h daily.0 && du -hc daily.1
29G /daily.0
29G /daily.1

Ahora dele directorios en la misma fila (comenzando con el más reciente para copias de seguridad incrementales de rsync con --link-dest):

$ du -hc daily.0 daily.1
29G /daily.0
364M /daily.1
29G total

O todo el directorio de respaldo:

$ du -hc --max-depth=1 /snapshots
29G /daily.0
364M /daily.1
537M /daily.2
333M /daily.3
30G total

No se contará ningún archivo en 'daily.1' que haga referencia a un inodo (también conocido como archivo "real") ya mencionado en 'daily.0'.

Por lo tanto, eliminar diariamente.1 ahorrará 364MB en su dispositivo.

ELIMINAR

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.