14.4. Reading a Directory's Contents It is common for a program to need a list of the files contained in a directory. Linux provides a set of functions that allow a directory to be handled as an abstract entity to avoid forcing programs to depend on the exact format of directories employed by a file system. Opening and closing directories is straightforward. #include <dirent.h> DIR * opendir(const char * pathname); int closedir(DIR * dir); opendir() returns a pointer to a DIR data type, which is abstract (just like stdio's FILE structure) and should not be manipulated outside the C library. As directories may be opened only for reading, it is not necessary to specify what mode the directory is opened with. opendir() succeeds only if the directory exists it cannot be used to create new directories (use mkdir() for that). Closing a directory can fail only if the dir parameter is invalid. Once the directory has been opened, directory entries are read sequentially until the end of the directory is reached. readdir() returns the name of the next file in the directory. Directories are not ordered in any way, so do not assume that the contents of the directory are sorted. If you need a sorted list of files, you must sort the file names yourself. The readdir() function is defined like this: #include <dirent.h> struct dirent * readdir(DIR * dir); A pointer to a struct dirent is returned to the caller. Although struct dirent contains multiple members, the only one that is portable is d_name, which holds the file name of the directory entry. The rest of struct dirent's members are system specific. The only interesting one of these is d_ino, which contains the inode number of the file. The only tricky part of this is determining when an error has occurred. Unfortunately, readdir() returns NULL if an error occurs or if there are no more entries in the directory. To differentiate between the two cases, you must check errno. This task is made more difficult by readdir() not changing errno unless an error occurs, which means errno must be set to a known value (normally, 0) before calling readdir() to allow proper error checking. Here is a simple program that writes the names of the files in the current directory to stdout: 1: /* dircontents.c */ 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: /* "." is the current directory */ 12: if (!(dir = opendir("."))) { 13: perror("opendir"); 14: return 1; 15: } 16: 17: /* set errno to 0, so we can tell when readdir() fails */ 18: errno = 0; 19: while ((ent = readdir(dir))) { 20: puts(ent->d_name); 21: /* reset errno, as puts() could modify it */ 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. Starting Over If you need to reread the contents of a directory that has already been opened with opendir(), rewinddir() resets the DIR structure so that the next call to readdir() returns the first file in the directory. #include <dirent.h> int rewinddir(DIR * dir); |