Какой самый быстрый / простой способ подсчета большого количества файлов в каталоге (в Linux)? - PullRequest
10 голосов
/ 21 мая 2011

У меня был какой-то каталог с большим количеством файлов. Каждый раз, когда я пытался получить доступ к списку файлов в нем, я не мог этого сделать или существенная задержка. Я пытался использовать команду ls в командной строке в Linux, и веб-интерфейс от моего хостинг-провайдера также не помог.

Проблема в том, что когда я просто делаю ls, требуется значительное время, чтобы даже начать что-то отображать. Таким образом, ls | wc -l также не поможет.

После некоторых исследований я придумал этот код (в этом примере он подсчитывает количество новых писем на каком-либо сервере):

print sum([len(files) for (root, dirs, files) in walk('/home/myname/Maildir/new')])

Приведенный выше код написан на Python. Я использовал инструмент командной строки Python, и он работал довольно быстро (мгновенно возвращал результат).

Меня интересует ответ на следующий вопрос: можно ли посчитать файлы в каталоге (без подкаталогов) быстрее? Какой самый быстрый способ сделать это?

Ответы [ 7 ]

6 голосов
/ 21 мая 2011

ls делает stat(2) вызов для каждого файла. Другие инструменты, такие как find(1) и расширение подстановочного знака оболочки, могут избежать этого вызова и просто сделать readdir. Одной из возможных комбинаций команд оболочки является find dir -maxdepth 1|wc -l, но она с удовольствием перечислит сам каталог и пропустит любое имя файла с новой строкой в ​​нем.

В Python простой способ получить только эти имена - os.listdir (directory) . В отличие от os.walk и os.path.walk, он не требует рекурсии, проверки типов файлов или дальнейших вызовов функций Python.

Приложение: Кажется, ls не всегда стат. По крайней мере, в моей системе GNU он может выполнять только вызов getdents, когда дополнительная информация (например, какие имена являются каталогами) не запрашивается. getdents - основной системный вызов, используемый для реализации readdir в GNU / Linux.

Дополнение 2: Одна из причин задержки перед выводом результатов ls заключается в том, что она сортирует и табулирует. ls -U1 может этого избежать.

3 голосов
/ 21 мая 2011

Это должно быть довольно быстро в Python:

from os import listdir
from os.path import isfile, join
directory = '/home/myname/Maildir/new'
print sum(1 for entry in listdir(directory) if isfile(join(directory,entry)))
3 голосов
/ 21 мая 2011

Общее количество файлов в данном каталоге

find . -maxdepth 1 -type f | wc -l

Общее количество файлов в данном каталоге и всех подкаталогах в нем

find . -type f | wc -l

Для получения более подробной информации перейдите в терминал идо man find

1 голос
/ 22 мая 2011

Самый быстрый способ состоит в том, чтобы избежать накладных расходов на интерпретируемые языки и написать некоторый код, который напрямую решает вашу проблему. Это трудно сделать портативным способом, но довольно просто. На данный момент я нахожусь на OS X box, но преобразование следующего в Linux должно быть очень простым. (Я решил игнорировать скрытые файлы и считать только обычные файлы ... измените при необходимости или добавьте параметры командной строки, чтобы получить нужные функции.)


#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>

int
main( int argc, char **argv )
{
    DIR *d;
    struct dirent *f;
    int count = 0;
    char *path = argv[ 1 ];

    if( path == NULL ) {
        fprintf( stderr, "usage: %s path", argv[ 0 ]);
        exit( EXIT_FAILURE );
    }
    d = opendir( path );
    if( d == NULL ) { perror( path );exit( EXIT_FAILURE ); }
    while( ( f = readdir( d ) ) != NULL ) {
        if( f->d_name[ 0 ] != '.'  &&  f->d_type == DT_REG )
            count += 1;
    }
    printf( "%d\n", count );
    return EXIT_SUCCESS;
}

1 голос
/ 21 мая 2011

Я думаю, ls тратит большую часть своего времени перед отображением первой строки, потому что он должен отсортировать записи, поэтому ls -U должен отображать первую строку намного быстрее (хотя в целом это может быть не так уж и лучше).

0 голосов
/ 02 марта 2017

Мой пример использования - Linux SBC (Banana Pi), подсчитывающий файлы в каталоге на USB-накопителе FAT32.В оболочке выполнение

ls -U {dir} | wc -l

занимает 6,4 сек с 32k файлами там (32k = max files / dir на FAT32) Из python выполнение

t=time.time() ; print len(os.listdir(d)) ; print time.time()-t

занимает всего 0,874 сек (!) В Python не вижу ничего более быстрого, чем это.

0 голосов
/ 21 мая 2011

Я не уверен насчет скорости, но если вы хотите просто использовать встроенные оболочки, это должно работать:

#!/bin/sh
COUNT=0;
for file in /path/to/directory/*
do
COUNT=$(($COUNT+1));
done
echo $COUNT
...