Як `du` лише простір, який використовується файлами, які не мають жорсткого посилання в іншому місці?


14

Використання rsync --link-destдля економії простору знімків , як я можу зрозуміти, скільки місця я на самому ділі врятований? Або більш загальне:

Як розібратися, скільки місця займає каталог, враховуючи лише файли, які не є жорсткими посиланнями в іншому місці за межами структури каталогу? Запитали інакше: скільки місця фактично було б звільнено після видалення цього каталогу? ( du -hsбреше. Можливо, буде включено місце, необхідне для самих жорстких посилань)


2
За замовчуванням GNU duпідраховує розміри файлів лише один раз, навіть якщо вони жорстко пов'язані, якщо ви не використовуєте параметр -l/ --count-links. Ви працюєте duпо всьому дереву двічі, з цією опцією та без неї, а різниця між розмірами повинна бути стільки, скільки ви зберегли в усіх каталогах.
jw013

1
Дивіться також stackoverflow.com/questions/19951883 / ...
Rmano

Відповіді:


9

Якщо припустити, що немає внутрішніх жорстких посилань (тобто кожен файл з більш ніж 1 жорсткою посиланням пов'язаний з-за дерева), ви можете:

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

EDIT І ось те, що я замалював у коментарі, застосував. Тільки без du; kudos to @StephaneChazelas зауважувати duне потрібно. Пояснення в кінці.

( 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

Ми робимо це, щоб створити рядок із використанням диска (у КБ) кожного відповідного файлу, розділеного знаками плюс. Тоді ми годуємо це велике доповнення bc.

Перше findвиклик робить це для каталогів.

Друга findдрукує кількість посилань, кількість inode та використання диска. Ми передаємо цей список, sort | uniq -cщоб отримати список (кількість появи у дереві, кількість посилань, inode, використання диска).

Ми передаємо цей список через awk, і якщо перше поле (кількість показів) більше або дорівнює другому (# твердих посилань), тобто немає посилань на цей файл із-за дерева, а потім надрукуємо четверте поле ( використання диска) зі знаком плюс та додається зворотна косої риски.

Нарешті ми виводимо a 0, тому формула є синтаксично правильною (вона б спричинила +інакше) і передаємо її bc. Phew.

(Але я б застосував простіший перший метод, якщо він дає досить хорошу відповідь.)


Дякую, так, якщо ця вимога виконується, вона працює. Але що робити, якщо це не так?
Тобіас Кіенцлер

Це не працює, оскільки не враховує розмір самих каталогів (які, як правило, мають принаймні 2 посилання, а якби вони не були, у вас були б файли, що рахуються двічі).
Стефан Шазелас

1
Тоді слід було б скористатися findдля друку списку всіх файлів із їхніми входами та кількістю посилань; потім деяка комбінація, sort | uniq -cщоб отримати скільки разів кожен inode з'являється на дереві, потім відфільтруйте ті, які мають кількість посилань, більша за кількість показів ..., а потім подайте цей список у du. Але якщо вимога буде виконана, краще заощадите зусилля.
angus

@StephaneChazelas Це працює, але це правда, що він не враховує власний розмір каталогів. Якби duбув -dпараметр, подібний до lss s ...
angus

Також зауважте, що у btrfsфайлових системах кількість посилань на каталоги завжди є 1, тому вам потрібно буде додати! -type d
Stéphane Chazelas

5

В основному потрібно отримати номери inode та кількість посилань для всіх файлів (не-каталогів), порівняти це число посилань із кількістю зустрічей кожного inode, і якщо вони різняться, виключити файл.

Якщо припустити, що вони всі в одній файловій системі, щось подібне повинно працювати (з 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
     }'

Так, що я сказав (дякую за кредит). Але додаткову точність, яку ви отримуєте, перераховуючи каталоги, ви втрачаєте, додаючи неточне використання диска.
angus

@angus, що ти маєш на увазі під "неточним використанням диска"?
Стефан Шазелас

Нічого, я абсолютно помилився з приводу того, що %kповідомив. Це чудово, duзовсім не потрібно! Я оновлю свою відповідь, коли повернусь додому. Спасибі!
angus

3

du фактично не буде брехати;) Він аналізує дір (и), який він дає, рахуючи лише першу з усіх жорстких посилань, що вказують на той самий інод, з яким він стикається.

Якщо ви запитаєте, duщо він бачить лише в одному каталозі, це не хвилює, чи є інші жорсткі посилання, що вказують на той самий вміст:

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

Тепер дайте йому dirs у тому ж рядку (починаючи з останнього для додаткового резервного копіювання rsync --link-dest):

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

Або весь резервний реж:

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

Будь-який файл у "daily.1", на який посилається inode (він же "реальний" файл), на який уже посилається "daily.0", не буде зарахований.

Тому видалення щодня1 заощадить 364 Мб на вашому пристрої.

ВИДАЛИТИ

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.