16

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

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

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

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

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

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

5 ответов5

9

В некоторых версиях 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
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
4

Предполагая, что вы используете du из GNU 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 используется для многократного подсчета жестких ссылок, потому что единственная причина для хранения номеров устройств и индексов заключается в пропуске файлов с жесткими ссылками, которые уже были обработаны.)

Если вы хотите получить удобочитаемое представление общего размера, просто добавьте опцию -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
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

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

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

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

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}'

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .