Як отримати фактичний розмір каталогу (з du)?


17

Як отримати фактичний розмір каталогу за допомогою стандартних інструментів UNIX / Linux?

Альтернативне запитання: Як мені отримати ду, щоб показати мені фактичний розмір каталогу (не використання диска)?

Оскільки, здається, люди мають різні визначення терміна "розмір": Моє визначення "розміру каталогу" - це сума всіх регулярних файлів у цьому каталозі.

Я НЕ дбаю про розмір inode каталогу або будь-який інший (блоки * розмір блоку) файлів у відповідній файловій системі. Каталог з 3-ма файлами, по 1 байті кожен, має розмір каталогу в 3 байти (за моїм визначенням).

Обчислення розміру каталогу за допомогою du здається ненадійним.
Наприклад, mkdir foo && du -b fooзвіти "4096 foo", 4096 байт замість 0 байт. У дуже великих каталогах розмір каталогів, про який повідомляється, du -hsможе бути вимкнений на 100 ГБ (!) Та більше (стисла файлова система).

Отже, що (інструмент / варіант) потрібно використовувати для отримання фактичного розміру каталогу?


Яка файлова система використовується в новому місці - це xfsвипадково?
Сергій Власов


І якщо ваш новий FS справді XFS, значно збільшене використання диска, ймовірно, пов’язане з агресивним попереднім розміщенням , що зменшує фрагментацію файлів за рахунок використання диска.
Сергій Власов

Відповіді:


8

Ось сценарій, що відображає читаний людиною розмір каталогу за допомогою стандартних інструментів 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()}'

наприклад:

$ ds ~        
72.891 GiB

А тепер я знайшов ще один варіант , який відсутній в усіх запропонованих lsзаклинаннях тут: -q. Без цієї опції сценарій порушиться, якщо якесь ім'я файлу містить символи нового рядка. Писати справді надійні сценарії оболонок - надто важко ...
Сергій Власов

@SergeyVlasov Сценарій, який я опублікував, не повинен зриватися з такими файлами, а лише ігнорувати зайві рядки. Єдиний проблемний випадок стався б у тому випадку, коли у ретельно складеного файлу була додаткова лінія з п’ятою двокрапкою, яка містить числове значення. Ваша пропозиція справді уникне такої ситуації. Дякуємо за пораду, сценарій оновлено.
jlliagre

Відмінна відповідь. +1 до вас, сер
ehime

Це одне з найнадійніших рішень. Він працює з іменами файлів, у яких є пробіли або лапки, і він друкує людський розмір.
основні6

@KIAaze Дякую за перегляд та виправлення мого коду!
jlliagre

8

Деякі версії duпідтримують аргумент --apparent-sizeпоказувати видимий розмір замість використання диска. Отже, ваша команда буде:

du -hs --apparent-size

З довідкових сторінок для du, включених до 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

1
не працює: повідомте про місце для порожніх панів
Карл Форнер

1
це працювало для мене.
конорбоде

2
Він дає значно різні розміри, коли ви порівнюєте каталоги в різних файлових системах. Наприклад, ця папка має очевидний розмір 290Gb у файловій системі zfs та 324Gb exFat. Розчини, наведені вище, надають однаковий розмір.
Pixus.ru

4

Просто альтернатива, використовуючи ls:

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

ls -nR: -nяк -l, але перераховуйте числові UID та GID та -Rпідкаталоги списку рекурсивно.

grep -v:Інвертуйте відчуття відповідності, щоб вибрати невідповідні лінії. (-v визначається POSIX.). '^ d'виключить каталоги.

Команда Ls: http://linux.about.com/od/commands/l/blcmdl1_ls.htm

Людина Греп: http://linux.die.net/man/1/grep

Редагувати :

Відредаговано як пропозиція @ Сергій Власов.


Використання -nпараметра lsзамість -l(показувати UID / GID номери замість імен) є більш безпечним, оскільки імена користувачів та груп можуть містити пробіли (наприклад, якщо winbindабо sssdвикористовується для приєднання системи до домену Windows, ви можете отримати назви груп на зразок domain users) . Він також повинен бути швидшим через відсутність необхідності пошуку імен користувачів та груп.
Сергій Власов

Дякую, це набагато швидше, ніж знайти -exec ls!
gpothier

4

Якщо припустити, що ви маєте duGNU coreutils, ця команда повинна обчислити загальний видимий розмір довільної кількості регулярних файлів всередині каталогу без будь-яких довільних обмежень на кількість файлів:

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

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

Найголовніша відмінність від звичайного du -sbполягає в тому, що рекурсивний duтакож рахує розміри каталогів, про які по-різному повідомляють різні файлові системи; щоб уникнути цього, findкоманда використовується для передачі лише звичайних файлів du. Ще одна відмінність полягає в тому, що символьні посилання ігноруються (якщо їх слід порахувати, тоfind команду слід скорегувати).

Ця команда також буде споживати більше пам'яті , ніж звичайний du -sb, тому що з допомогою --files0-from=FILEробить duмагазин пристрою і номера індексних дескрипторів з усіх оброблених файлів, на відміну від поведінки за замовчуванням запам'ятовування тільки файли з більш ніж однієї жорсткої посилання. (Це не проблема, якщо ця -lопція використовується для підрахунку твердих посилань кілька разів, тому що єдиною причиною для зберігання номерів пристрою та inode є пропуск файлів, які вже були оброблені.)

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

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

або (якщо ви переживаєте, що деякі наслідки -bпотім будуть відмінені -h)

find . -type f -print0 | du -sc --apparent-size -h --files0-from=- | tail -n 1

Не впевнений, що робити для FreeBSD - хоча, -bможливо, її можна замінити -A -B 1, немає еквівалента --files0-from=-, і для використання xargsзнадобляться деякі шляхові вирішення у випадку, якщо список файлів більший, ніж ARG_MAX(і якесь зовнішнє рішення для людського читаного виводу).
Сергій Власов

3

Якщо все, що вам потрібно, - це розмір файлів, виключаючи простір, який займають каталоги, ви можете зробити щось подібне

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

@SergeyVlasov зазначив, що це не вдасться, якщо у вас більше файлів, ніж argmax. Щоб уникнути того, що ви можете використовувати щось на кшталт:

find . -type f -exec du -sb '{}' \; | gawk '{k+=$1}END{print k}'

1
Ця команда мовчки дасть неправильний результат, якщо каталог містить стільки файлів, що вони не вміщуються в обмеження розміру аргументів execve () - в цьому випадку xargsбуде викликатися duкілька разів, і кожне виклик буде надрукувати загальну суму просто зі своєї частини повного списку файлів, тоді tailвідображатиметься лише загальний розмір останньої частини.
Сергій Власов

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