Чтение онлайн

на главную - закладки

Жанры

Разработка приложений в среде Linux. Второе издание

Троан Эрик В.

Шрифт:

После открытия каталога его элементы читаются последовательно до конца каталога.

Системный вызов

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

#include <dirent.h>

struct dirent * readdir (DIR * dir);

Вызывающему коду возвращается указатель на структуру

struct dirent
. Несмотря на то что
struct dirent
содержит несколько элементов, единственным переносимым элементом является
d_name
, содержащий имя файла элемента каталога. Остальные элементы
struct dirent
зависят от системы. Однако интересным является элемент
d_ino
, содержащий inode-номер файла.

Самой сложной частью этого процесса является определение ошибки. К сожалению,

readdir
возвращает
NULL
, и когда происходит ошибка, и когда в каталоге больше нет элементов. Чтобы различать эти две ситуации, необходимо проверять
errno
. Эта задача усложняется тем, что
readdir
не меняет
errno
, пока не произойдет ошибка. Это означает, что для корректной проверки ошибок
errno
необходимо установить перед вызовом
readdir
в заранее известное значение (обычно 0). Ниже показана простая программа, записывающая имена файлов текущего каталога в stdout.

 1: /* dircontents.с */

 2:

 3: #include <errno.h>

 4: #include <dirent.h>

 5: #include <stdio.h>

 6:

 7: int main(void) {

 8: DIR * dir;

 9: struct dirent * ent;

10:

11: /* "." - текущий каталог */

12: if (!(dir = opendir("."))) {

13: perror("opendir");

14: return 1;

15: }

16:

17: /* установить errno в 0, чтобы можно было выяснить, когда readdir даст сбой*/

18: errno = 0;

19: while ((ent = readdir(dir))) {

20: puts (ent->d_name);

21: /* сбросить errno, поскольку puts может модифицировать ее */

22: errno = 0;

23: }

24:

25: if (errno) {

26: perror("readdir");

27: return 1;

28: }

29:

30: closedir(dir);

31:

32: return 0;

33: }

14.4.1. Прохождение по каталогу

Если требуется перечитать содержимое каталога, уже открытого

opendir
, с помощью
rewinddir
структура
DIR
сбрасывается, чтобы следующий вызов
readdir
мог вернуть первый файл в каталоге.

#include <dirent.h>

int rewinddir(DIR * dir);

14.5. Универсализация файловых имен

Большинство

пользователей Linux принимают как должное то, что запуск
ls *.с
не сообщает сведения о файле в текущем каталоге, именем которого является
*.с
. Вместо этого они ожидают увидеть список всех файлов в текущем каталоге, имена которых заканчиваются на
. Это расширение имени файла от
*.с
до
ladsh.с dircontents.с
(например) обычно обрабатывается оболочкой, которая универсализирует все параметры для программ, выполняющихся под ее управлением. Программы, помогающие пользователям манипулировать файлами, тоже часто нуждаются в универсализации файловых имен. Существуют два распространенных способа универсализации имен файлов внутри программ.

14.5.1. Использование подпроцесса

Самый старый метод универсализации предусматривает запуск оболочки в качестве дочернего процесса и указание ей универсализировать файловые имена. Стандартная функция

popen
(см. главу 10) упрощает этот метод — просто запустите команду
ls *.с
с помощью
popen
и прочитайте результат. Этот подход может показаться несколько упрощенным, но все же он обеспечивает переносимое решение проблемы универсализации (вот почему приложения вроде Perl используют его).

Ниже приведена программа, которая универсализирует все аргументы и отображает все совпадения.

 1: /* popenglob.c */

 2:

 3: #include <stdio.h>

 4: #include <string.h>

 5: #include <sys/wait.h>

 6: #include <unistd.h>

 7:

 8: int main(int argc, const char ** argv)

 9: char buf[1024];

10: FILE * ls;

11: int result;

12: int i;

13:

14: strcpy(buf, "ls");

15:

16: for (i = 1; i < argc; i++) {

17: strcat(buf, argv[i]);

18: strcat(buf, " ");

19: }

20:

21: ls = popen(buf, "r");

22: if (!ls) {

23: perror("popen");

24: return 1;

25: }

26:

27: while (fgets(buf, sizeof(buf), ls))

28: printf("%s", buf);

29:

30: result = pclose(ls);

31:

32: if (!WIFEXITED(result)) return 1;

33:

34: return 0;

35: }

14.5.2. Внутренняя универсализация

Если необходимо универсализировать несколько файловых имен, запуск нескольких подоболочек с помощью

popen
будет неэффективным. Функция
glob
позволяет универсализировать имена файлов без запуска каких-либо подпроцессов, однако за счет увеличения сложности и снижения переносимости. Несмотря на то что вызов
glob
описан в стандарте POSIX.2, многие варианты Unix до сих пор его не поддерживают.

Поделиться:
Популярные книги

Неудержимый. Книга VIII

Боярский Андрей
8. Неудержимый
Фантастика:
фэнтези
попаданцы
аниме
6.00
рейтинг книги
Неудержимый. Книга VIII

Законы Рода. Том 6

Flow Ascold
6. Граф Берестьев
Фантастика:
юмористическое фэнтези
аниме
5.00
рейтинг книги
Законы Рода. Том 6

Восход. Солнцев. Книга I

Скабер Артемий
1. Голос Бога
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Восход. Солнцев. Книга I

Попаданка

Ахминеева Нина
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Попаданка

Возлюби болезнь свою

Синельников Валерий Владимирович
Научно-образовательная:
психология
7.71
рейтинг книги
Возлюби болезнь свою

Кодекс Крови. Книга III

Борзых М.
3. РОС: Кодекс Крови
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Кодекс Крови. Книга III

Ротмистр Гордеев 2

Дашко Дмитрий
2. Ротмистр Гордеев
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Ротмистр Гордеев 2

Идеальный мир для Лекаря 5

Сапфир Олег
5. Лекарь
Фантастика:
фэнтези
юмористическая фантастика
аниме
5.00
рейтинг книги
Идеальный мир для Лекаря 5

Адвокат Империи 3

Карелин Сергей Витальевич
3. Адвокат империи
Фантастика:
городское фэнтези
попаданцы
аниме
фэнтези
фантастика: прочее
5.00
рейтинг книги
Адвокат Империи 3

Жребий некроманта 3

Решетов Евгений Валерьевич
3. Жребий некроманта
Фантастика:
боевая фантастика
5.56
рейтинг книги
Жребий некроманта 3

Город драконов

Звездная Елена
1. Город драконов
Фантастика:
фэнтези
6.80
рейтинг книги
Город драконов

Убивать, чтобы жить

Бор Жорж
1. УЧЖ
Фантастика:
героическая фантастика
боевая фантастика
рпг
5.00
рейтинг книги
Убивать, чтобы жить

Инквизитор Тьмы 2

Шмаков Алексей Семенович
2. Инквизитор Тьмы
Фантастика:
попаданцы
альтернативная история
аниме
5.00
рейтинг книги
Инквизитор Тьмы 2

Беглец

Бубела Олег Николаевич
1. Совсем не герой
Фантастика:
фэнтези
попаданцы
8.94
рейтинг книги
Беглец