List Files within a Directory Recursively in C

To list files within a directory recursively using C, you can use POSIX functions (opendir, readdir, and stat) and the nftw() function.


Example 1: Recursively Listing Files using opendir, readdir, and stat

In this example, we will manually traverse directories by opening each directory with opendir, reading its contents with readdir, and checking file attributes using stat. If an entry is a subdirectory, the function recursively calls itself to list its contents.

Explanation:

  1. opendir(path): Opens the directory specified by path and returns a directory pointer.
  2. readdir(dp): Reads the next entry in the directory pointed to by dp.
  3. We skip the special entries "." and ".." using strcmp.
  4. snprintf: Constructs a new path by combining the current path with the entry name.
  5. stat(newPath, &statbuf): Retrieves file status; S_ISDIR checks if the entry is a directory.
  6. If the entry is a directory, the function listFiles is called recursively on the new path.

Program:

</>
Copy
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <sys/stat.h>
#include <string.h>

void listFiles(const char *path) {
    struct dirent *entry;
    DIR *dp = opendir(path);
    if (dp == NULL) {
        perror("opendir");
        return;
    }

    while ((entry = readdir(dp)) != NULL) {
        // Skip the current and parent directory entries
        if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
            continue;
        printf("%s/%s\n", path, entry->d_name);
        
        // Build the new path for the directory entry
        char newPath[1024];
        snprintf(newPath, sizeof(newPath), "%s/%s", path, entry->d_name);

        // Check if the entry is a directory
        struct stat statbuf;
        if (stat(newPath, &statbuf) == 0 && S_ISDIR(statbuf.st_mode)) {
            listFiles(newPath);
        }
    }
    closedir(dp);
}

int main() {
    listFiles(".");
    return 0;
}

Sample Output:

./file1.txt
./dir1
./dir1/file2.txt
...

Example 2: Recursively Listing Files using nftw()

In this example, we will use the nftw() function from the <ftw.h> library to traverse the directory tree. The nftw() function simplifies recursive traversal by handling the recursion internally and calling a user-defined callback function for each file or directory encountered.

Explanation:

  1. nftw(".", printFile, 20, 0): Starts the traversal from the current directory ("."). The number 20 specifies the maximum number of directories that can be open simultaneously, and 0 indicates the default behavior.
  2. The callback function printFile is invoked for every file or directory encountered during the traversal.
  3. printFile: This function simply prints the full path of the current file or directory.

Program:

</>
Copy
#define _XOPEN_SOURCE 500
#include <ftw.h>
#include <stdio.h>

int printFile(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf) {
    printf("%s\n", fpath);
    return 0;
}

int main() {
    nftw(".", printFile, 20, 0);
    return 0;
}

Sample Output:

./file1.txt
./dir1
./dir1/file2.txt
...

Conclusion

In this tutorial, we demonstrated two different approaches to list files within a directory recursively using C:

  1. Manual Traversal: Uses opendir, readdir, and stat to manually traverse directories and recursively list their contents.
  2. Using nftw(): Leverages the nftw() function to simplify recursive traversal by internally managing the recursion and invoking a callback for each entry.