суммарный размер файлов в каталоге
Подскажите, с помощью какой команды можно узнать РЕАЛЬНЫЙ суммарный размер файлов в каталоге, не в блоках, а тупо в килобайтах (соответственно, команду du не предлагать, потому что она выдает завышенный результат).
Re: суммарный размер файлов в каталоге
т.е. du -b не годится?
Re: суммарный размер файлов в каталоге
> узнать РЕАЛЬНЫЙ суммарный размер файлов в каталоге
подскажите, с помощью какой команды можно узнать НЕ РЕАЛЬНЫЙ размер файлов в каталоге?
Re: суммарный размер файлов в каталоге
Re: суммарный размер файлов в каталоге
эмм. а разве в линуксе, по дефолту, размер блока не равен килобайту? :S т.е. чем не катит du -ksh ?
Re: суммарный размер файлов в каталоге
ну смотрите: имеется папка test, в ней два файла: 1 — пустой, 11 — весом в 15 байт. что имеем: du -ab ./test 15 ./test/11 0 ./test/1 4111 ./test
т.е. получается, что по отдельности он размеры файлов нормально определяет, а суммарный итог почему-то выдает неправильный. почему?
Re: суммарный размер файлов в каталоге
>а суммарный итог почему-то выдает неправильный. почему?
а почему вы считаете что это неправильный итог? при
du -ab test будет выдан размер файлов и самой директории
Re: суммарный размер файлов в каталоге
Потому что я всю жизнь считал, что размер «самой директории» равен сумме размеров всех фалов, содержащихся в ней. Тогда по вашей логике выдаваемый размер должен быть в 2 раза больше, чем реальный, но это не так.
Или я ошибаюсь, и размер самой директории это что-то другое?
Re: суммарный размер файлов в каталоге
конечно. каталог — это по сути файл, который имеет размер.
Найти суммарный размер всех регулярных файлов в каталоге, рекурсивно обходя все подкаталоги
Сама задача следующая: программа получает на вход в аргументах командной строки имя каталога и печатает на стандартный поток вывода суммарный размер (в байтах) всех регулярных файлов в нем. При этом пропускать все записи, являющиеся символическими ссылками.
У меня есть написанная программа, которая успешно выдает какие-то числа, но я не знаю, как убедиться в том, что она выдает правильный ответ. Подскажите, пожалуйста:
1) Можно ли как-то решить исходную задачу средствами bash (команда ls и так далее)?
2) Какие могут быть «крайние» случаи, на которых программу стоит протестировать? Ну кроме пустого каталога.
2 ответа 2
Чтобы подсчитать суммарный размер обычных файлов ( S_ISREG ) в заданном дереве директорий, пропуская все symlinks, на Питоне:
Вывод показывает, что общий размер всех обычных файлов в /usr директории, около 7 GB.
Python, listdir()
Для проверки, я реализовал get_tree_size() , не используя os.scandir() :
Результаты одинаковые в данном случае, но в общем случае они могут отличаться (например, os.listdir() возвращает список (сразу все имена), а os.scandir() возвращает итератор, поэтому os.scandir() может учесть больше имен, а os.listdir() пропустит всю директорию, если произойдёт ошибка c получением хотя бы одного имени в директории). Код для примеров адаптирован из Python issue: PEP 471 implementation: os.scandir() directory scanning function.
Внимание: размер файла и занимаемое место на диске могут отличаться.
Bash, du
1) Можно ли как-то решить исходную задачу средствами bash (команда ls и так далее)?
Можно, конечно, но результаты могут немного отличаться (см. тестовые случаи). Если нужны точные результаты, то несложно написать программу, с точным необходимым поведением как показывают примеры кода на Питоне выше.
du -bs . возвращает значение, которое превышает суммарные размеры файлов, например:
Суммарный размер: 820 + 631 == 1451 :
что ожидаемо (Питон возвращает правильный результат), но du возвращает неверный результат:
-b опция уже включает в себя —apparent-size (то есть результат уже не отражает занимаемое место на диске — как и хотелось).
du считает также размеры всех каталогов, которые они занимают на диске.
Что подтверждается экспериментами:
Результат для du стал больше, что согласуется c комментарием @avp.
Если выключить —apparent-size , то du возвращает занимаемое место на диске:
Что ещё больше отличается от суммарного размера файлов.
2) Какие могут быть «крайние» случаи, на которых программу стоит протестировать? Ну кроме пустого каталога.
Потестировать имена файлов, директорий, начинающихся на точку ( .zshrc , .ssh ).
Потестировать на директории со специальными файлами, например, /dev директория может содержать /dev/sda файл, который не является обычным файлом (это диск — блочное устройство S_ISBLK ) или FIFO ( S_ISFIFO ) (можно создать командой: mkfifo /tmp/named_pipe ).
Или потестировать на директориях с нечитаемыми записями, например, из-за недостатка прав доступа (командой chmod можно подготовить).
И, конечно, потестировать на директориях, содержащих символические ссылки ( S_ISLNK ), которые ссылаются как на обычные файлы так и на другие директории.
Для проверки надёжности, можно сгенерировать глубоко-вложенные директории с именами записей разной длины, состоящих из произвольных байтов (всё кроме слэша / и нулевого байта ‘\0’ , если локальная система не вносит своих ограничений).
С, nftw()
Для сравнения, можно посмотреть на примеры кода на С/С++. Для рекурсивного обхода дерева директорий, можно nftw() использовать:
Пример: $ gcc get-tree-size-ftw.c && ./a.out
Чтобы передать дополнительные переменные ( size ) в visit_path() обратный вызов, gcc позволяет использовать вложенные функции.
В общем случае, для более тонкого контроля обхода дерева директорий, к примеру, чтобы пропустить всё внутри .git и других подобных директорий, есть fts_open() API, добавив fnmatch() API, можно реализовать аналог команды:
С, readdir()
При желании, можно руками с помощью readdir() рекурсивный обход директории выполнить:
- директория задаётся с помощью dirfd это позволяет избежать каждый раз от корня все пути просматривать, так как entry->d_name содержит только последнюю часть пути. В противном случае пришлось бы создавать путь от входной (с которой вызов начался) директории каждый раз, прежде чем путь в stat() передать
- специальные имена «.» и «..» явно пропускаются
- используется AT_SYMLINK_NOFOLLOW , чтобы не следовать по символическим ссылкам, чтобы получить информацию о самой записи ( entry )
- ошибки по индивидуальным записям явно игнорируются
В C++ рекурсивно обойти дерево директорий можно используя библиотеку:
- символические ссылки, указывающие как на директории так и на обычные файлы пропускаются
- «.» и «..» записи также пропускаются
- ошибки доступа и ошибки при чтении статуса файла игнорируются, но цикл может исключения выбрасывать в случае других ошибок.
Пример: $ g++ -std=c++11 *.cc -lstdc++fs && ./a.out (для ). В С++17 можно просто #include использовать. Библиотека также доступна как #include :
Все варианты кода для подсчёта суммарного размера выдают один и тот же результат в обычных случаях, но возможны отличия, когда исключительные ситуации по разному обрабатываются.
Производительность ограничивается скоростью диска. Если мета-данные уже закэшированы в памяти, то вариант с медленнее, чем nftw() и readdir() , которые похоже себя ведут. код только немного медленнее кода на Питоне.
Как подсчитать размер файлов и папок в Linux?
Умение работать с данными размеров дисков и папок в системе Linux один из важных моментов, которые должен уметь решать администратор сервера. На нашем сайте уже были посты о различных командах для просмотра информации о системе, в частности такой команды как df, которая позволяют получать информацию о разделах, их размеров в частности. В данном посту мы рассмотрим команду просмотра информации о размерах папок в системах Unix.
Для просмотра информации о занимаемом объеме файлов и папок системе мы можем воспользоваться стандартной программой для Unix систем – du (сокр. disc usage).
Синтаксис команды du
Опции команды du
–b вывод информации в байтах
–c вывод итоговой информации об использовании дисковой памяти
–k вывод информации в килобайтах(по умолчанию)
–s вывод итоговой информации об использовании дискового пространства без информации о каталогах
-h вывод информации в человеко-читаемом виде
Примеры использования команды du
Чтобы показать общий объем текущего каталога, со всеми вложенными файлами и подкаталогами, можно воспользоваться командой du с опцией –sh:
Так же можно подсчитать размер всех файлов и директорий в текущем каталоге, а затем вывести данные в виде списка, для этого к опции указанной выше следует добавить звездочку — *:
Так же можно просмотреть размеры всех вложенных файлов и подпапок, однако стоит помнить, что в для больших объемов данных может потребоваться значительное время пока команда сможет выполниться, и в некоторых случаях это не всегда рационально. Если все-таки процесс затянулся на длительное время, вы всегда можете его отметить посредством комбинации клавиш Ctrl+C.
Для более удобного восприятия данных есть возможность сортировки списка по занимаемому объему. Для этого следует ввести команду со следующими опциями:
Команда отобразит список файлов и папок отсортированный по объему занимаемых данных, величина будет указываться в килобайтах.
То же самое, только в мегабайтах:
Казалось бы, более удобная опция h в данном случае была весьма кстати (вывод в Kb, Mb, Gb), но, к сожалению, она здесь не подходит, но есть выход – это использовать такую команду:
Строка ввода команды получилась достаточно длинная, но вывод при этом получается довольно читабелен для глаз человека.