Программа превращает каталог в подкаталоги, чтобы у найденных файлов были пригодные для использования имена, т.е. они могут передаваться непосредственно в функцию opendir. Программа будет давать сбои при просмотре структур с большим числом уровней вложенности, поскольку есть ограничение на разрешенное число открытых потоков каталогов.
Мы могли бы сделать программу более универсальной, принимая в качестве аргумента командной строки начальную точку просмотра.
Для того чтобы познакомиться с методами повышения универсальности программ, посмотрите исходный код таких утилит Linux, как
lsfind1. Начните с соответствующих заголовочных файлов и функции
printdirdepth#include <unistd.h>#include <stdio.h>#include <dirent.h>#include <string.h>#include <sys/stat.h>#include <stdlib.h>void printdir(char *dir, int depth) { DIR *dp; struct dirent *entry; struct stat statbuf; if ((dp = opendir(dir)) == NULL) { fprintf(stderr, "cannot open directory: %s\n", dir); return; } chdir(dir); while((entry = readdir(dp)) != NULL) { lstat(entry->d_name, &statbuf); if (S_ISDIR(statbuf.st_mode)) { /* Находит каталог, но игнорирует . и .. */ if (strcmp(".", entry->d_name) == 0 || strcmp("..", entry->d_name) == 0) continue; printf("%*s%s/\n", depth, "", entry->d_name); /* Рекурсивный вызов с новый отступом */ printdir(entry->d_name, depth+4); } else printf("%*s%s\n", depth, " ", entry->d_name); } chdir(".."); closedir(dp);}2. Теперь переходите к функции
mainint main() { /* Обзор каталога /home */ printf("Directory scan of /home:\n"); printdir("/home", 0); printf("done.\n"); exit(0);}Программа просматривает исходные каталоги и формирует вывод, похожий на приведенный далее (отредактированный для краткости). Для того чтобы заглянуть в каталоги других пользователей, вам могут понадобиться права доступа суперпользователя.
$ <b>./printdir</b>Directory scan of /home:neil/ .Xdefaults .Xmodmap .Xresources .bash_history .bashrc .kde/ share/ apps/ konqueror/ dirtree/ public_html.desktop toolbar/ bookmarks.xml konq_history kdisplay/ color-schemes/ BLP4e/ Gnu_Public_License chapter04/ argopt.с args.с chapter03/ file.out mmap.с printdirdone.Как это работает
Большинство операций сосредоточено в функции
printdiropendirprintdirchdirreaddirdepthЕсли элемент — каталог, вы встречаетесь с рекурсией. После игнорирования элементов
...printdirwhilechdir("..")closedir(dp)Для того чтобы составить представление об окружении в системе Linux, обсуждаемом в главе 4, познакомьтесь с одним из способов, повышающих универсальность программы. Рассматриваемая программа ограничена, потому что привязана каталогу /home. Следующие изменения в функции
main