Швидкий кількість файлів Linux для великої кількості файлів


137

Я намагаюся знайти найкращий спосіб знайти кількість файлів у конкретному каталозі, коли файлів дуже велика (> 100 000).

Коли файлів так багато, виконання файлів ls | wc -lзаймає досить багато часу. Я вважаю, що це тому, що він повертає назви всіх файлів. Я намагаюся зайняти якомога менше дискового вводу.

Я експериментував з деякими сценаріями оболонки та Perl безрезультатно. Будь-які ідеї?


2
переконайтеся, що ваш "ls" є / usr / bin / ls, а не псевдонім для чогось фантазії.
glenn jackman

Подібне запитання з цікавими відповідями тут: serverfault.com/questions/205071/…
aidan

Варто зазначити, що більшість, якщо не всі рішення, представлені в цьому питанні, не характерні лише для Linux , але є досить загальними для всіх * NIX-подібних систем. Можливо, видалення тегу "Linux" доречно.
Крістофер Шульц

Відповіді:


189

За замовчуванням lsсортуйте імена, що може зайняти деякий час, якщо їх багато. Також не буде результату, поки всі назви не будуть прочитані та відсортовані. Використовуйте ls -fопцію, щоб вимкнути сортування.

ls -f | wc -l

Зверніть увагу , що це також дозволить -a, так ., ..і інші файли , що починаються з .враховуватимуться.


11
+1 І я подумав, що знаю все, про що треба знати ls.
моб

5
ЗОМГ. Сортування ліній 100K - це нічого - порівняно з stat()викликом lsу кожному файлі. findНЕ stat()таким чином , він працює швидше.
Dummy00001

12
ls -fтеж не має stat(). Але, звичайно, обидва lsі findдзвонять, stat()коли використовуються певні параметри, наприклад, ls -lабо find -mtime.
mark4o

7
У контексті на це знадобилося 1-2 хвилини, щоб порахувати 2,5 мільйона jpgs на маленькій коробці Slicehost.
philfreo

6
Якщо ви хочете додати до підрахунків підкаталоги, зробіть цеls -fR | wc -l
Райан Уоллс

62

Найшвидший спосіб - це цілеспрямована програма, наприклад:

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

int main(int argc, char *argv[]) {
    DIR *dir;
    struct dirent *ent;
    long count = 0;

    dir = opendir(argv[1]);

    while((ent = readdir(dir)))
            ++count;

    closedir(dir);

    printf("%s contains %ld files\n", argv[1], count);

    return 0;
}

З мого тестування, не зважаючи на кеш, я запускав кожне з них приблизно по 50 разів кожен і той же каталог, знову і знову, щоб уникнути перекосу даних на основі кешу, і я отримав приблизно такі показники продуктивності (в режимі реального часу):

ls -1  | wc - 0:01.67
ls -f1 | wc - 0:00.14
find   | wc - 0:00.22
dircnt | wc - 0:00.04

Останнє dircnt, - це програма, складена з вищевказаного джерела.

EDIT 2016-09-26

Зважаючи на популярність, я переписав цю програму на рекурсивну, тому вона потрапить у підкаталоги та продовжуватиме рахувати файли та каталоги окремо.

Оскільки зрозуміло, що деякі люди хочуть знати, як все це зробити, у мене є багато коментарів у коді, щоб спробувати зробити це очевидним, що відбувається. Я написав це і протестував його на 64-бітному Linux, але він повинен працювати в будь-якій системі, сумісній з POSIX, включаючи Microsoft Windows. Звіти про помилки вітаються; Я радий оновити це, якщо ви не можете працювати з AIX або OS / 400 чи іншим.

Як бачите, це набагато складніше, ніж оригінал і обов'язково так: принаймні одна функція повинна існувати, щоб викликати рекурсивно, якщо ви не хочете, щоб код став дуже складним (наприклад, керування стеком підкаталогів та обробка цього в одному циклі). Оскільки ми маємо перевірити типи файлів, відмінності між різними ОС, стандартними бібліотеками тощо вступають у гру, тому я написав програму, яка намагається бути корисною для будь-якої системи, де вона буде компілюватися.

Перевірки помилок дуже мало, а сама countфункція насправді не повідомляє про помилки. Єдині дзвінки, які дійсно можуть бути невдалими, є opendirі stat(якщо вам не пощастило та у вас система, де вже direntє тип файлу). Я не параноїчний щодо перевірки загальної довжини імен шляхів субдір, але теоретично система не повинна допускати жодного імені шляху, що перевищує ніж PATH_MAX. Якщо є проблеми, я можу це виправити, але це просто більше коду, який потрібно пояснити тому, хто вчиться писати C. Ця програма призначена для прикладу того, як занурюватися в підкаталоги рекурсивно.

#include <stdio.h>
#include <dirent.h>
#include <string.h>
#include <stdlib.h>
#include <limits.h>
#include <sys/stat.h>

#if defined(WIN32) || defined(_WIN32) 
#define PATH_SEPARATOR '\\' 
#else
#define PATH_SEPARATOR '/' 
#endif

/* A custom structure to hold separate file and directory counts */
struct filecount {
  long dirs;
  long files;
};

/*
 * counts the number of files and directories in the specified directory.
 *
 * path - relative pathname of a directory whose files should be counted
 * counts - pointer to struct containing file/dir counts
 */
void count(char *path, struct filecount *counts) {
    DIR *dir;                /* dir structure we are reading */
    struct dirent *ent;      /* directory entry currently being processed */
    char subpath[PATH_MAX];  /* buffer for building complete subdir and file names */
    /* Some systems don't have dirent.d_type field; we'll have to use stat() instead */
#if !defined ( _DIRENT_HAVE_D_TYPE )
    struct stat statbuf;     /* buffer for stat() info */
#endif

/* fprintf(stderr, "Opening dir %s\n", path); */
    dir = opendir(path);

    /* opendir failed... file likely doesn't exist or isn't a directory */
    if(NULL == dir) {
        perror(path);
        return;
    }

    while((ent = readdir(dir))) {
      if (strlen(path) + 1 + strlen(ent->d_name) > PATH_MAX) {
          fprintf(stdout, "path too long (%ld) %s%c%s", (strlen(path) + 1 + strlen(ent->d_name)), path, PATH_SEPARATOR, ent->d_name);
          return;
      }

/* Use dirent.d_type if present, otherwise use stat() */
#if defined ( _DIRENT_HAVE_D_TYPE )
/* fprintf(stderr, "Using dirent.d_type\n"); */
      if(DT_DIR == ent->d_type) {
#else
/* fprintf(stderr, "Don't have dirent.d_type, falling back to using stat()\n"); */
      sprintf(subpath, "%s%c%s", path, PATH_SEPARATOR, ent->d_name);
      if(lstat(subpath, &statbuf)) {
          perror(subpath);
          return;
      }

      if(S_ISDIR(statbuf.st_mode)) {
#endif
          /* Skip "." and ".." directory entries... they are not "real" directories */
          if(0 == strcmp("..", ent->d_name) || 0 == strcmp(".", ent->d_name)) {
/*              fprintf(stderr, "This is %s, skipping\n", ent->d_name); */
          } else {
              sprintf(subpath, "%s%c%s", path, PATH_SEPARATOR, ent->d_name);
              counts->dirs++;
              count(subpath, counts);
          }
      } else {
          counts->files++;
      }
    }

/* fprintf(stderr, "Closing dir %s\n", path); */
    closedir(dir);
}

int main(int argc, char *argv[]) {
    struct filecount counts;
    counts.files = 0;
    counts.dirs = 0;
    count(argv[1], &counts);

    /* If we found nothing, this is probably an error which has already been printed */
    if(0 < counts.files || 0 < counts.dirs) {
        printf("%s contains %ld files and %ld directories\n", argv[1], counts.files, counts.dirs);
    }

    return 0;
}

EDIT 2017-01-17

Я включив дві зміни, запропоновані @FlyingCodeMonkey:

  1. Використовуйте lstatзамість stat. Це змінить поведінку програми, якщо ви посилаєтесь на каталоги в сканованому каталозі. Попередня поведінка полягала в тому, що (пов'язаний) підкаталог буде додавати до загального підрахунку кількість файлів; нова поведінка полягає в тому, що пов'язаний каталог буде рахуватися як один файл, а його вміст не буде зараховано.
  2. Якщо шлях файлу занадто довгий, надсилатиметься повідомлення про помилку, і програма зупиняється.

EDIT 2017-06-29

При будь-якій удачі, це буде остання редакція цієї відповіді :)

Я скопіював цей код у сховище GitHub, щоб полегшити отримання коду (замість копіювання / вставки, ви можете просто завантажити джерело ), а також полегшити можливість запропонувати модифікацію, подавши потяг -запит від GitHub.

Джерело доступне під ліцензією Apache License 2.0. Патчі * Ласкаво просимо!


  • "латка" - це те, що старі люди, як я, називають "запитом на витяг".

2
Просто здорово! Дякую! А для тих, хто не знає: ви можете виконати вищезазначений код у терміналі: gcc -o dircnt dircnt.cі використовувати так./dircnt some_dir
aesede

Чи є простий спосіб зробити це рекурсивним?
ck_

@ck_ Звичайно, це легко зробити рекурсивним. Вам потрібна допомога з рішенням, чи ви хочете, щоб я написав всю справу?
Крістофер Шульц

1
@ChristopherSchultz, тести, які ви опублікували вище - наскільки великим був каталог, про який йде мова?
Дом Він'ярд

1
Я дуже хотів використовувати це в Python, тому я упакував його як пакет ffcount . Дякуємо, що зробили код доступним @ChristopherSchultz!
GjjvdBurg

35

Ви спробували знайти? Наприклад:

find . -name "*.ext" | wc -l

1
Це буде рекурсивно знаходити файли в поточному каталозі.
mark4o

У моїй системі find /usr/share | wc -l(~ 137 000 файлів) приблизно на 25% швидше, ніж ls -R /usr/share | wc -l(~ 160 000 рядків, включаючи назви dir, підсумки dir та порожні рядки) під час першого запуску кожного та принаймні вдвічі швидше при порівнянні наступних (кешованих) прогонів.
Призупинено до подальшого повідомлення.

11
Якщо він хоче лише поточний каталог, а не все дерево рекурсивно, він може додати параметр -maxdepth 1 для пошуку.
igustin

3
Здається, причина findшвидша, ніж lsчерез те, як ви користуєтесь ls. Якщо ви припините сортування lsта findмаєте подібну продуктивність.
Крістофер Шульц

17

find, ls та perl протестовано проти 40 000 файлів: однакова швидкість (хоча я не намагався очистити кеш):

[user@server logs]$ time find . | wc -l
42917

real    0m0.054s
user    0m0.018s
sys     0m0.040s
[user@server logs]$ time /bin/ls -f | wc -l
42918

real    0m0.059s
user    0m0.027s
sys     0m0.037s

і з perl opendir / readdir, одночасно:

[user@server logs]$ time perl -e 'opendir D, "."; @files = readdir D; closedir D; print scalar(@files)."\n"'
42918

real    0m0.057s
user    0m0.024s
sys     0m0.033s

Примітка: я використовував / bin / ls -f, щоб переконатися в тому, щоб обійти опцію псевдоніму, яка може трохи сповільнити і -f, щоб уникнути впорядкування файлів. ls без -f вдвічі повільніше, ніж find / perl, за винятком випадків, коли ls використовується з -f, здається, це той же час:

[user@server logs]$ time /bin/ls . | wc -l
42916

real    0m0.109s
user    0m0.070s
sys     0m0.044s

Я також хотів би мати якийсь сценарій, щоб запитати файлову систему безпосередньо, не маючи зайвої інформації.

тести, засновані на відповіді Пітера ван дер Хайдена, Глена Джекмана та mark4o.

Томас


5
Ви обов'язково повинні очистити кеш-пам'ять між тестами. Перший раз, коли я запускаю ls -l | wc -lпапку на зовнішньому 2,5-дюймовому HDD з файлами 1M, для завершення операції потрібно близько 3 хвилин. Вдруге IIRC займає 12 секунд. Також це може залежати і від вашої файлової системи. використовував Btrfs.
Беранг Саедзаде

Дякую, фрагмент perl - це рішення для мене. $ time perl -e 'opendir D, "."; @files = readdir D; closedir D; print scalar(@files)."\n"' 1315029 real 0m0.580s user 0m0.302s sys 0m0.275s
Pažout

5

Ви можете змінити вихід на основі своїх вимог, але ось базовий однофайл, який я написав, щоб рекурсивно рахувати та повідомляти про кількість файлів у ряді каталогів, що мають цифрову назву.

dir=/tmp/count_these/ ; for i in $(ls -1 ${dir} | sort -n) ; { echo "$i => $(find ${dir}${i} -type f | wc -l),"; }

Це виглядає рекурсивно для всіх файлів (а не каталогів) у даній папці та повертає результати у хеш-форматі. Прості налаштування команди find можуть зробити, які файли ви шукаєте, щоб підрахувати більш конкретні тощо.

Результати в чомусь подібному:

1 => 38,
65 => 95052,
66 => 12823,
67 => 10572,
69 => 67275,
70 => 8105,
71 => 42052,
72 => 1184,

1
Я знайшов приклад трохи заплутаним. Мені було цікаво, чому зліва замість імен каталогів стоять цифри. Дякую за це, хоча я в кінцевому підсумку скористався цим кількома незначними налаштуваннями. .. (рахункові каталоги і скинувши бази папки ім'я для г в $ (Ls -1 | сортувати -n); {відлуння "$ я => $ (знайти $ {я} | туалет -l)";}
TheJacobTaylor

Цифри зліва - це мої назви каталогів з моїх прикладних даних. Вибачте, що було заплутано.
mightybs

1
ls -1 ${dir}не працюватимуть належним чином без пробілів. Крім того, немає гарантії, що ім'я, яке повертається, lsможе бути передано find, оскільки воно lsне використовує символи для друку для споживання людиною. ( mkdir $'oddly\nnamed\ndirectory'якщо ви хочете особливо цікавий тестовий випадок). Дивіться, чому ви не повинні розбирати вихід ls (1)
Чарльз Даффі,

4

Дивно, але для мене знахідка голих кісток дуже порівнянна з ls -f

> time ls -f my_dir | wc -l
17626

real    0m0.015s
user    0m0.011s
sys     0m0.009s

проти

> time find my_dir -maxdepth 1 | wc -l
17625

real    0m0.014s
user    0m0.008s
sys     0m0.010s

Звичайно, значення на третьому десятковому місці дещо зміщуються щоразу, коли ви виконуєте будь-яке з них, тож вони в основному однакові. Однак зауважте, що findповертає один зайвий блок, оскільки він рахує сам фактичний каталог (і, як згадувалося раніше, ls -fповертає два зайві одиниці, оскільки він також рахує. І ..).


4

Просто додайте це заради повноти. Правильну відповідь, звичайно, вже розмістив хтось інший, але ви також можете отримати кількість файлів і каталогів з деревньою програмою.

Виконайте команду, tree | tail -n 1щоб отримати останній рядок, який буде говорити приблизно як "763 каталоги, 9290 файлів". Це підраховує файли та папки рекурсивно, виключаючи приховані файли, які можна додати разом із прапором -a. Для довідки на моєму комп’ютері знадобилося 4,8 секунди, щоб дерево порахувало весь мій домашній dir, який складав 24777 каталогів, 238680 файлів. find -type f | wc -lпішло на 5,3 секунди, на півсекунди довше, тому я думаю, що дерево досить конкурентоспроможне.

Поки у вас немає підпапок, дерево - це швидкий і простий спосіб підрахунку файлів.

Крім того, і для задоволення це ви можете використовувати tree | grep '^├'лише для показу файлів / папок у поточному каталозі - це в основному набагато повільніше версія ls.


Brew install tailдля OS X.
The Unfun Cat

@TheUnfunCat tailвже має бути встановлений у вашій системі Mac OS X.
Крістофер Шульц

4

Швидкий кількість файлів Linux

Найшвидший підрахунок файлів Linux, який я знаю

locate -c -r '/home'

Там немає ні необхідності викликати Grep! Але, як згадувалося, у вас повинна бути свіжа база даних (щодня оновлюється роботою з крон або вручну sudo updatedb)

Від людини знайдіть

-c, --count
    Instead  of  writing  file  names on standard output, write the number of matching
    entries only.

Додатково слід знати, що він також зараховує каталоги як файли!


BTW: Якщо ви хочете переглянути огляд своїх файлів та каталогів вашого типу системи

locate -S

Він видає кількість каталогів, файлів тощо.


зауважте, що ви повинні переконатися, що база даних
оновлена

1
LOL, якщо у вас вже є всі рахунки в базі даних, то ви, звичайно, можете швидко порахувати. :)
Крістофер Шульц

3

Пишу це тут, оскільки мені не вистачає репутаційних балів, щоб коментувати відповідь, але мені дозволяють залишити власну відповідь, що не має сенсу. Все одно ...

Щодо відповіді Крістофера Шульца , я пропоную змінити stat на lstat і, можливо, додати перевірку меж, щоб уникнути переповнення буфера:

if (strlen(path) + strlen(PATH_SEPARATOR) + strlen(ent->d_name) > PATH_MAX) {
    fprintf(stdout, "path too long (%ld) %s%c%s", (strlen(path) + strlen(PATH_SEPARATOR) + strlen(ent->d_name)), path, PATH_SEPARATOR, ent->d_name);
    return;
}

Запропонувати використовувати lstat - уникати наступних посилань, які можуть призвести до циклів, якщо каталог містить символьне посилання на батьківський каталог.


2
Модифікація, оскільки використання lstatбуло гарною пропозицією, і ви заслужили карму для цього. Ця пропозиція була включена в мій код, розміщений вище, і тепер, на GitHub.
Крістофер Шульц

2

Ви могли б спробувати , якщо використовується opendir()і readdir()в Perlшвидше. Для прикладу цих функцій дивіться тут


2
використання: perl -e 'opendir D, "."; @files = readdir D; закритір D; print skalar (@files) '
glenn jackman

2

Ця відповідь тут швидше, ніж майже все інше на цій сторінці для дуже великих, дуже вкладених каталогів:

https://serverfault.com/a/691372/84703

locate -r '.' | grep -c "^$PWD"


1
Приємно. Оскільки у вас вже є оновлений db всіх файлів, не потрібно повторювати його. Але, на жаль, ви повинні переконатися, що оновлена ​​команда вже запущена та виконана для цього методу.
Кріс Рейд

вам не потрібно грепати. Використовуйте locate -c -r '/path'як у рішенні abu_bua
phuclv

2

Я прийшов сюди, коли намагався підрахувати файли в наборі даних ~ 10K папок з ~ 10K файлами в кожній. Проблема багатьох підходів полягає в тому, що вони неявно статують 100M файли, що займає віки.

Я взяв на себе можливість поширити підхід на christopher-schultz, щоб він підтримував передачу каталогів через args (його рекурсивний підхід також використовує stat).

Помістіть у файл наступне dircnt_args.c:

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

int main(int argc, char *argv[]) {
    DIR *dir;
    struct dirent *ent;
    long count;
    long countsum = 0;
    int i;

    for(i=1; i < argc; i++) {
        dir = opendir(argv[i]);
        count = 0;
        while((ent = readdir(dir)))
            ++count;

        closedir(dir);

        printf("%s contains %ld files\n", argv[i], count);
        countsum += count;
    }
    printf("sum: %ld\n", countsum);

    return 0;
}

Після цього gcc -o dircnt_args dircnt_args.cви можете викликати його так:

dircnt_args /your/dirs/*

На 100M файлах у папках 10K вищезазначене завершується досить швидко (~ 5 хв для першого запуску, подальших дій у кеші: ~ 23 с).

Єдиний підхід , який закінчив менш ніж через годину був Ls з приблизно 1 хв на кеш: ls -f /your/dirs/* | wc -l. Кількість відключається на пару нових рядків за день, хоча ...

Крім очікуваного, жодна з моїх спроб не findповернулася протягом години: - /


Для когось, хто не є програмістом на С, ви можете пояснити, чому це було б швидше, і як він може отримати ту саму відповідь, не роблячи те саме?
mlissner

вам не потрібно бути програмістом на C, просто зрозумійте, що означає статистика файлу та як представлені каталоги: каталоги по суті є списками імен файлів та узорів. Якщо ви статте файл, ви отримуєте доступ до inode, який знаходиться десь на диску, наприклад, щоб отримати інформацію, наприклад, розмір файлу, дозволи, .... Якщо вас просто цікавлять підрахунки за один день, вам не потрібно отримувати доступ до інформації про введення, що може заощадити багато часу.
Йорн Хес

Цей перехід на Oracle linux, gcc версія 4.8.5 20150623 (Red Hat 4.8.5-28.0.1) (GCC) ... відносні шляхи та віддалені файли, здається, є причиною
Рондо

2

Найшвидший спосіб для Linux (питання позначено як Linux) - це використання прямого системного виклику. Ось невеличка програма, яка рахує файли (тільки, без dirs) у каталозі. Ви можете порахувати мільйони файлів, і це приблизно в 2,5 рази швидше, ніж "ls -f" і приблизно в 1,3-1,5 рази швидше, ніж відповідь Крістофера Шульца.

#define _GNU_SOURCE
#include <dirent.h>
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/syscall.h>

#define BUF_SIZE 4096

struct linux_dirent {
    long d_ino;
    off_t d_off;
    unsigned short d_reclen;
    char d_name[];
};

int countDir(char *dir) {


    int fd, nread, bpos, numFiles = 0;
    char d_type, buf[BUF_SIZE];
    struct linux_dirent *dirEntry;

    fd = open(dir, O_RDONLY | O_DIRECTORY);
    if (fd == -1) {
        puts("open directory error");
        exit(3);
    }
    while (1) {
        nread = syscall(SYS_getdents, fd, buf, BUF_SIZE);
        if (nread == -1) {
            puts("getdents error");
            exit(1);
        }
        if (nread == 0) {
            break;
        }

        for (bpos = 0; bpos < nread;) {
            dirEntry = (struct linux_dirent *) (buf + bpos);
            d_type = *(buf + bpos + dirEntry->d_reclen - 1);
            if (d_type == DT_REG) {
                // Increase counter
                numFiles++;
            }
            bpos += dirEntry->d_reclen;
        }
    }
    close(fd);

    return numFiles;
}

int main(int argc, char **argv) {

    if (argc != 2) {
        puts("Pass directory as parameter");
        return 2;
    }
    printf("Number of files in %s: %d\n", argv[1], countDir(argv[1]));
    return 0;
}

PS: Це не рекурсивно, але ви можете змінити його для досягнення цього.


1
Я не впевнений, що згоден, що це швидше. Я не простежив все, що робить компілятор opendir/ readdir, але я підозрюю, що з часом він зводиться до майже того ж коду. Здійснення системних викликів таким чином також не є портативним, а оскільки Linux ABI не є стабільним, програма, складена в одній системі, не гарантує належну роботу в іншій (хоча це досить хороша порада компілювати що-небудь із джерела в будь-якій * NIX-системі IMO ). Якщо швидкість є ключовою, це хороше рішення, якщо вона фактично покращує швидкість - я не орієнтував програми окремо.
Крістофер Шульц

1

lsвитрачає більше часу на сортування імен файлів, використовуючи -fдля відключення сортування, економиться колись:

ls -f | wc -l

або ви можете використовувати find:

find . -type f | wc -l

0

Я зрозумів, що не використовувати в обробці пам'яті, коли у вас є величезна кількість даних, це найшвидше, ніж "прошивати" команди. Тому я зберег результат у файл і після його аналізу

ls -1 /path/to/dir > count.txt && cat count.txt | wc -l

це не найшвидше рішення, оскільки жорсткі диски надзвичайно повільні. Є й інші ефективніші способи, розміщені за роки до вас
phuclv

0

Ви повинні використовувати "getdents" замість ls / find

Ось одна дуже хороша стаття, в якій описаний підхід до роботи.

http://be-n.com/spw/you-can-list-a-million-files-in-a-directory-but-not-with-ls.html

Ось витяг:

ls і практично кожен інший метод лістингу каталогу (включаючи python os.listdir, find.) покладаються на libc readdir (). Однак readdir () одночасно читає лише 32K записів каталогів, а це означає, що якщо у вас є багато файлів у тому ж каталозі (тобто 500M записів каталогів), вам знадобиться шалено тривалий час, щоб прочитати всі записи каталогів , особливо на повільному диску. Для каталогів, що містять велику кількість файлів, вам потрібно буде викопати глибше, ніж інструменти, які покладаються на readdir (). Вам потрібно буде скористатися системою виклику getdents () безпосередньо, а не допоміжними методами від libc.

Ми можемо знайти код C для переліку файлів за допомогою getdents () звідси :

Вам потрібно буде зробити дві модифікації, щоб швидко перерахувати всі файли в каталозі.

По-перше, збільште розмір буфера від X до приблизно, як 5 мегабайт.

#define BUF_SIZE 1024*1024*5

Потім змініть основний цикл, де він виводить інформацію про кожен файл у каталозі, щоб пропустити записи з inode == 0. Я зробив це, додавши

if (dp->d_ino != 0) printf(...);

У моєму випадку я також дійсно піклувався лише про назви файлів у каталозі, тому я також переписав заяву printf (), щоб друкувати лише ім'я файлу.

if(d->d_ino) printf("%sn ", (char *) d->d_name);

Скомпілюйте його (йому не потрібні зовнішні бібліотеки, тому це зробити дуже просто)

gcc listdir.c -o listdir

Тепер просто біжи

./listdir [directory with insane number of files]

Зауважте, що Linux робить читання вперед, тому readdir()насправді це не повільно. Мені потрібна солідна цифра, перш ніж я вважаю, що для цього підвищення продуктивності варто скинути портативність.
фуз

-1

Я віддаю перевагу наступній команді для відстеження змін у кількості файлів у каталозі.

watch -d -n 0.01 'ls | wc -l'

Команда зберігає вікно відкритим, щоб відстежувати кількість файлів, що знаходяться в каталозі, зі швидкістю оновлення 0,1 сек.


ви впевнені, що ls | wc -lзакінчите папку з тисячами або мільйонами файлів за 0,01 секунди? навіть ваш lsнадзвичайно неефективний порівняно з іншими рішеннями. А ОП просто хочуть зараховувати, а не сидіти там, дивлячись на зміну результатів
phuclv

Ну. Ну. Я знайшов елегантне рішення, яке працює для мене. Я хотів би поділитися тим самим, отже, зробив. Я не знаю, що команда 'ls' в Linux є дуже неефективною. Що ви використовуєте замість цього? І 0,01s - швидкість оновлення. Не час. якщо ви не використовували годинник, перегляньте сторінки чоловіків.
Anoop Toffy

добре, я читав watchпосібник після цього коментаря і бачу, що 0,01 сек (а не 0,1 с) - це нереальне число, оскільки частота оновлення більшості екранів ПК становить лише 60 ГГц, і це ніяк не відповідає на питання. ОП запитала про "Швидкий кількість файлів Linux для великої кількості файлів". Ви також не читали жодних доступних відповідей перед публікацією
phuclv

Я читав відповіді. Але те, що я розмістив - це спосіб відстеження зміни кількості файлів у каталозі. наприклад: під час копіювання файлу з одного місця в інше кількість файлів зберігається. за допомогою методу, який я планую, можна це відслідковувати. Я погоджуюся, що публікація, яку я зробив, не там, де змінювати або покращувати будь-які попередні повідомлення.
Anoop Toffy

-2

Перші 10 директорій з найбільшою кількістю файлів.

dir=/ ; for i in $(ls -1 ${dir} | sort -n) ; { echo "$(find ${dir}${i} \
    -type f | wc -l) => $i,"; } | sort -nr | head -10

3
Це, безумовно, виглядає приголомшливо схожим на відповідь (з тими ж помилками), яку написав mightybs . Якщо ви збираєтесь розширити або змінити код, написаний кимось іншим, доцільно зарахувати їх. Розуміння коду, який ви використовуєте у своїх відповідях, достатньо для виявлення та виправлення помилок, є ще більш доцільним.
Чарльз Даффі
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.