Быстрый способ узнать количество файлов в одном каталоге в Linux

Я ищу быстрый способ найти количество файлов в каталоге в Linux.

Любое решение, которое требует линейного времени по количеству файлов в каталоге, НЕ приемлемо (например, «ls | wc -l» и подобные вещи), потому что это заняло бы чрезмерно много времени (есть десятки или, может быть, сотни миллионов файлов). файлы в каталоге).

Я уверен, что количество файлов в каталоге должно храниться как простое число где-то в структуре файловой системы (возможно, inode?), как часть структуры данных, используемой для хранения записей каталога - как я могу добраться до этого числа?

Изменить: файловая система ext3. Если нет портативного способа сделать это, я готов сделать что-то конкретное для ext3.


person HighCommander4    schedule 19.07.2010    source источник
comment
Почти дубликат: stackoverflow.com/questions/1427032/, рассказывает о том, как ускорить стандартный ls | туалет-л   -  person Mark    schedule 19.07.2010
comment
Я не думаю, что это где-то хранится как простое число (хотя я НЕ читал спецификацию). Просто потому, что это будет тормозить ФС, вам нужно будет синхронизировать touch/unlink/mv и т. д., чтобы получить надежный результат, также в случае сбоя номер может быть поврежден, поэтому вам нужно будет пересчитать файлы в какой-то момент . Кроме того, по крайней мере, на моем Ubuntu Nautilus кэширует количество объектов в каталоге сам по себе, если бы в базовой FS было число, я не думаю, что это было бы так.   -  person Ivo Wetzel    schedule 19.07.2010
comment
Мне интересно... связан ли размер записи каталога (то есть размер, который вы видите для каталога, когда вы выполняете ls -l в его родительском каталоге) с количеством записей? Кажется, он больше, чем обычно для этого каталога.   -  person HighCommander4    schedule 19.07.2010
comment
размер каталога может быть соотнесен с максимальным количеством файлов, которые когда-либо хранились в нем. Каталог в некотором роде представляет собой обычный файл, содержащий разреженный массив с указателями на реальные файлы.   -  person Dummy00001    schedule 20.07.2010
comment
десятки, а может и сотни миллионов файлов — это патологический случай. Большое количество файлов в каталоге влияет на производительность; вот почему /usr/share/terminfo имеет подкаталог для каждого начального символа, используемого записью, поэтому его можно перемещать больше как дерево, чтобы уменьшить количество файлов. Существуют файловые системы, которые больше похожи на базы данных, где подсчет сводится к одному быстрому запросу, но они не распространены (если они вообще существуют вообще, IDK) в мире Unix.   -  person Stephen P    schedule 20.07.2010


Ответы (5)


Почему структура данных должна содержать число? Дереву не нужно знать свой размер в O (1), если только это не является требованием (и при этом может потребоваться больше блокировок и, возможно, узкое место в производительности)

Под деревом я подразумеваю не включение содержимого подкаталога, а файлы с -maxdepth 1 -- предположим, что они на самом деле не хранятся в виде списка.

edit: ext2 сохранил их как связанный список.

современный ext3 реализует хешированные B-деревья

Сказав это, /bin/ls делает гораздо больше, чем подсчитывает, и фактически сканирует все иноды. Напишите свою собственную программу или сценарий на C, используя opendir() и readdir().

из здесь:

#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
int main()
{
        int count;
        struct DIR *d;
        if( (d = opendir(".")) != NULL)
        {
                for(count = 0;  readdir(d) != NULL; count++);
                closedir(d);
        }
        printf("\n %d", count);
        return 0;
}
person Marco Mariani    schedule 19.07.2010
comment
На самом деле ls -a не читает больше данных из файловой системы, чем ваша программа, пока вы не передаете другие параметры, такие как --color или -F. Имейте в виду, что счетчик, возвращаемый ls -a или вашей программой, включает записи . и .. (поэтому пустой каталог имеет две записи). В Linux ls -A пропускает . и ... - person Gilles 'SO- stop being evil'; 20.07.2010
comment
а откуда он берет имена файлов? Я, кажется, помню, что для их получения требуется прочитать индексный дескриптор. но это было давно, может ты и прав. - person Marco Mariani; 20.07.2010
comment
@Gilles прав - имена файлов находятся в каталоге, а не в индексном узле файла (в конце концов, один индексный дескриптор файла может иметь много имен). Имена файлов доступны для написанной вами программы в d->d_name). - person caf; 20.07.2010

Вы можете использовать inotify для отслеживания и записи событий создания и отмены связи файлов в отслеживаемом каталоге. Это позволит распределить общее время, необходимое для поддержания количества файлов, и позволит вам мгновенно получить текущее количество файлов.

person Amardeep AC9MF    schedule 20.07.2010

Инод для каталога не хранит количество файлов в нем, так как обычно количество файлов не нужно отдельно от списка имен в каталоге. Счетчик ссылок индексного дескриптора каталога косвенно дает количество подкаталогов (st_nlink — это количество подкаталогов плюс два).

Я думаю, у вас нет другого выбора, кроме как прочитать весь список файлов в каталоге. find может или не может быть быстрее, чем ls.

Это пример того, почему большие каталоги представляют собой проблему, даже если каталог реализован с использованием B-дерева.

person Community    schedule 19.07.2010

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

person Matthew Flaschen    schedule 19.07.2010
comment
Мне не нужен портативный способ. Мне просто нужен способ. Файловая система ext3, если это имеет значение. - person HighCommander4; 19.07.2010

Если вы готовы прыгать через обручи, вы можете иметь каждый каталог в другой файловой системе, использовать квоты и получать информацию с помощью команды «repquota».

person Mark Wagner    schedule 19.07.2010