#include
#include
struct dirent *readdir(DIR *dirp);
Просмотр каталога с помощью функции readdir
не гарантирует формирование списка всех файлов (и подкаталогов) в каталоге, если в это время выполняются другие процессы, создающие и удаляющие файлы в каталоге.
В состав структуры dirent
, содержащей реквизиты элемента каталога, входят следующие компоненты.
□ ino_t d_ino
— индекс файла;
□ char d_name[]
— имя файла.
Для выяснения других реквизитов файла в каталоге вам необходимо вызвать stat
, который мы обсуждали ранее.
Функция telldir
возвращает значение, регистрирующее текущую позицию в потоке каталога. Вы можете использовать ее в последующих вызовах функции seekdir
для переустановки просмотра каталога, начиная с текущей позиции.
#include
#include
long int telldir(DIR *dirp);
Функция seekdir
устанавливает указатель на элемент каталога в потоке каталога, заданном в параметре dirp
. Значение параметра loc
, применяемого для установки позиции, следует получить из предшествующего вызова функции telldir
.
#include
#include
void seekdir (DIR *dirp, long int loc);
Функция closedir
закрывает поток каталога и освобождает ресурсы, выделенные ему. Она возвращает 0 в случае успеха и -1 при наличии ошибки.
#include
#include
int closedir(DIR *dirp);
В приведенной далее программе printdir.c (упражнение 3.4) вы соберете вместе множество функций обработки файлов для создания простого перечня содержимого каталога. Каждый файл представлен отдельной строкой. У каждого подкаталога есть имя, за которым следует слэш, и файлы, содержащиеся в подкаталоге, выводятся с отступом шириной в четыре пробела.
Программа превращает каталог в подкаталоги, чтобы у найденных файлов были пригодные для использования имена, т.е. они могут передаваться непосредственно в функцию opendir. Программа будет давать сбои при просмотре структур с большим числом уровней вложенности, поскольку есть ограничение на разрешенное число открытых потоков каталогов.
Мы могли бы сделать программу более универсальной, принимая в качестве аргумента командной строки начальную точку просмотра.
Для того чтобы познакомиться с методами повышения универсальности программ, посмотрите исходный код таких утилит Linux, как ls
и find
.
Упражнение 3.4. Программа просмотра каталога
1. Начните с соответствующих заголовочных файлов и функции printdir
, которая выводит содержимое текущего каталога. Она будет рекурсивно вызываться для вывода подкаталогов, применяя параметр depth
для задания отступа.
#include
#include
#include
#include
#include
#include
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. Теперь переходите к функции main
.
int main() {
/* Обзор каталога /home */
printf("Directory scan of /home:\n");
printdir("/home", 0);
printf("done.\n");
exit(0);
}
Программа просматривает исходные каталоги и формирует вывод, похожий на приведенный далее (отредактированный для краткости). Для того чтобы заглянуть в каталоги других пользователей, вам могут понадобиться права доступа суперпользователя.
$ ./printdir
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/
Читать дальше