scandir()
читает каталог, имя которого дано в dir
, создает с использованием malloc()
массив указателей struct dirent
и устанавливает *namelist
, чтобы он указывал на начало этого массива. Как массив указателей, так и указываемые структуры struct dirent
выделяются с помощью malloc()
; вызывающий код должен использовать free()
, чтобы избежать утечек памяти.
Для выбора нужных элементов используйте указатель функции select
. Когда это значение равно NULL
, все действительные элементы каталога включаются в конечный массив. В противном случае (*select)()
вызывается для каждого элемента, и те элементы, для которых она возвращает ненулевое (истинное) значение, включаются в массив.
Указатель функции compare сравнивает два элемента каталога. Он передается функции qsort()
для использования при сортировке.
alphasort()
лексикографически сравнивает имена файлов. Она использует для сравнения функцию strcoll()
. strcoll()
похожа на strcmp()
, но учитывает связанные с местной спецификой правила сортировки (см. раздел 13.4 «Не могли бы вы написать это для меня по буквам?»).
versionsort()
является расширением GNU, которое использует для сравнения имен файлов функцию GNU strverscmp()
(см.
В ch06-sortdir.c
приведена программа, похожая на ch04-catdir.c
. Однако, она использует для работы scandir()
и alphasort()
.
1 /* ch06-sortdir.c --- Демонстрирует scandir(), alphasort(). */
2
3 #include
4 #include
5 #include
6 #include
7
8 char *myname;
9 int process(const char *dir);
10
11 /* main --- перечислить аргументы каталога */
12
13 int main(int argc, char **argv)
14 {
15 int i;
16 int errs = 0;
17
18 myname = argv[0];
19
20 if (argc == 1)
21 errs = process("."); /* по умолчанию текущий каталог */
22 else
23 for (i = 1; i < argc; i++)
24 errs += process(argv[i]);
25
26 return (errs != 0);
27 }
28
29 /* nodots --- игнорирует файлы с точкой, для scandir() */
30
31 int
32 nodots(const struct dirent *dp)
33 {
34 return (dp->d_name[0] != '.');
35 }
36
37 /*
38 * process --- сделать что-то с каталогом, в данном случае,
39 * вывести в стандартный вывод пары индекс/имя.
40 * Вернуть 0, если все нормально, в противном случае 1.
41 */
42
43 int
44 process(const char *dir)
45 {
46 DIR *dp;
47 struct dirent **entries;
48 int nents, i;
49
50 nents = scandir(dir, &entries, nodots, alphasort);
51 if (nents < 0) {
52 fprintf(stderr, "%s: scandir failed: %s\n", myname,
53 strerror(errno));
54 return 1;
55 }
56
57 for (i = 0; i < nents; i++) {
58 printf("%81d %s\n", entries[i]->d_ino, entries[i]->d_name);
59 free(entries[i]);
60 }
61
62 free(entries);
63
64 return 0;
65 }
Функция main()
программы (строки 1–27) следует стандартному шаблону, который мы использовали до этого. Функция nodots()
(строки 31–35) действует как параметр select
, выбирая лишь имена файлов, которые не начинаются с точки.
Функция process()
(строки 43–65) довольно проста, причем scandir()
делает большую часть работы. Обратите внимание, как каждый элемент отдельно освобождается с помощью free()
(строка 59) и как освобождается также весь массив (строка 62).
При запуске содержимое каталога в самом деле выводится в отсортированном порядке, без '.
' и '..
'.