Как получить фактический размер каталога (из дю)?

17

Как узнать фактический размер каталога, используя стандартные инструменты UNIX / Linux?

Альтернативный вопрос: как мне заставить du показывать мне фактический размер каталога (не использование диска)?

Поскольку люди, похоже, имеют разные определения термина «размер»: мое определение «размера каталога» является суммой всех обычных файлов в этом каталоге.

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

Расчет размера каталога с использованием du кажется ненадежным.
Например, mkdir foo && du -b fooсообщает «4096 foo», 4096 байт вместо 0 байт. При очень больших каталогах размер каталога, о котором сообщается, du -hsможет быть отключен на 100 ГБ (!) И более (сжатая файловая система).

Так что (инструмент / опция) нужно использовать, чтобы получить фактический размер каталога?

basic6
источник
Какая файловая система используется в новом месте - это 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
jlliagre
источник
А теперь я нашел еще один вариант , который отсутствует во всех предложенных lsзаклинаниях здесь: -q. Без этой опции скрипт сломается, если какое-либо имя файла будет содержать символы новой строки. Написание действительно надежных сценариев оболочки слишком сложно…
Сергей Власов
@SergeyVlasov Сценарий, который я разместил, не должен ломаться с такими файлами, а просто игнорирует лишние строки. Единственный проблемный случай произошел бы, если бы у тщательно созданного файла была дополнительная строка с пятым двоеточием, которое содержит числовое значение. Ваше предложение действительно позволит избежать этой ситуации. Спасибо за совет, скрипт обновлен.
Jlliagre
Отличный ответ. +1 вам, сэр
Эхимэ
Это одно из самых надежных решений. Он работает с именами файлов, в которых есть пробелы или кавычки, и выводит читабельный размер.
basic6
@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
Это дает значительно разные размеры при сравнении каталогов в разных файловых системах. Например, та же папка имеет видимый размер 290 ГБ в файловой системе zfs и 324 ГБ exFat. Приведенные выше решения дают одинаковый размер.
Pixus.ru
4

Просто альтернатива, используя ls:

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

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

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

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

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

РЕДАКТИРОВАТЬ :

Отредактировано как предложение @ Сергей Власов.

STDERR
источник
Использование -nпараметра lsвместо вместо -l(показывать номера UID / GID вместо имен) более безопасно, поскольку имена пользователей и групп могут содержать пробелы (например, если winbindили sssdиспользуется для присоединения системы к домену Windows, вы можете получить такие имена групп, как domain users) , Это также должно быть быстрее из-за отсутствия необходимости поиска имен пользователей и групп.
Сергей Власов
Спасибо, это НАМНОГО быстрее, чем find -exec ls!
gpothier
4

Предполагая, что у вас есть duиз GNU coreutils, эта команда должна вычислить полный кажущийся размер произвольного числа обычных файлов в каталоге без каких-либо произвольных ограничений на количество файлов:

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

Добавьте эту -lопцию, duесли внутри есть несколько жестко связанных файлов, и вы хотите считать каждую жесткую ссылку отдельно (по умолчанию duнесколько жестких ссылок учитываются только один раз).

Самым важным отличием от plain du -sbявляется то, что рекурсив duтакже учитывает размеры каталогов, о которых разные файловые системы сообщают по-разному; чтобы избежать этого, findкоманда используется для передачи только обычных файлов du. Другое отличие состоит в том, что символические ссылки игнорируются (если они должны быть подсчитаны, findкоманда должна быть скорректирована).

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

Если вы хотите получить удобочитаемое представление общего размера, просто добавьте -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}'
terdon
источник
1
Эта команда будет молча давать неверный результат, если каталог содержит так много файлов, что они не помещаются в ограничение на размер аргументов execve () - в этом случае xargsбудет вызываться duнесколько раз, и каждый вызов будет выводить общую сумму только для его части из полного списка файлов, а затем tailпокажет только общий размер последней части.
Сергей Власов
1
@SergeyVlasov хороший момент, я не думал об этом, спасибо, ответ обновлен.
Тердон