8

Нередко мне приходится подсчитывать количество файлов в каталоге, иногда это исчисляется миллионами.

Есть ли лучший способ, чем просто перечислять и считать их с помощью find . | wc -l ? Есть ли какой-нибудь вызов файловой системы, который вы можете сделать в ext3/4, который требует меньше операций ввода-вывода?

3 ответа3

10

Не фундаментальное ускорение, но хоть что-то :)

find . -printf \\n | wc -l

Вам действительно не нужно передавать список имен файлов, достаточно только новых строк. Этот вариант примерно на 15% быстрее в моем Ubuntu 12.04.3, когда каталоги кэшируются в ОЗУ. Кроме того, этот вариант будет корректно работать с именами файлов, содержащими переводы строк.

Интересно, что этот вариант выглядит немного медленнее, чем приведенный выше:

find . -printf x | wc -c

Особый случай - но очень быстро

Если каталог находится в собственной файловой системе, вы можете просто посчитать inode:

df -i .

Если количество каталогов и файлов в других каталогах, отличных от подсчитанного, не сильно меняется, вы можете просто вычесть это известное число из текущего результата df -i . Таким образом, вы сможете очень быстро считать файлы и каталоги.

3

Я написал ffcnt именно для этой цели. Он извлекает физическое смещение самих каталогов с помощью fiemap ioctl, а затем планирует обход каталогов за несколько последовательных проходов, чтобы уменьшить произвольный доступ. Получаете ли вы на самом деле ускорение по сравнению с find | wc зависит от нескольких факторов:

  • Тип файловой системы: файловые системы, такие как ext4, которые поддерживают fiemap ioctl, выиграют больше всего
  • скорость произвольного доступа: преимущества жестких дисков намного выше, чем у твердотельных накопителей
  • макет каталога: чем больше количество вложенных каталогов, тем больше потенциал оптимизации

(повторное) монтирование с relatime или даже nodiratime может также улучшить скорость (для всех методов), когда доступ в противном случае вызовет обновления метаданных.

2

Собственно, в моей системе (Arch Linux) эта команда

   ls -A | wc -l

быстрее, чем все вышеперечисленное:

   $ time find . | wc -l
  1893

   real    0m0.027s
   user    0m0.004s
   sys     0m0.004s
   $ time find . -printf \\n  | wc -l
   1893

   real    0m0.009s
   user    0m0.000s
   sys     0m0.008s
   $ time find . -printf x  | wc -c
   1893

   real    0m0.009s
   user    0m0.000s
   sys     0m0.008s
   $ time ls -A | wc -l
   1892

   real    0m0.007s
   user    0m0.000s
   sys     0m0.004s

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