List All Files and Directories Recursively in C

To list all files and directories recursively using C, you can use approaches such as utilizing the opendir() and readdir() functions along with recursion, or alternatively, the nftw() function from <ftw.h>.


Example 1: Recursive Directory Listing Using opendir() and readdir()

In this example, we will create a program that uses opendir() and readdir() to open a directory, iterate through its entries, and then recursively call the same function to explore subdirectories. We will skip the "." and ".." entries to avoid infinite recursion.

main.c

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

void listFiles(const char *basePath) {
    char path[1000];
    struct dirent *dp;
    DIR *dir = opendir(basePath);

    if (dir == NULL) {
        return;
    }

    while ((dp = readdir(dir)) != NULL) {
        // Skip the names "." and ".."
        if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0)
            continue;

        // Print current file/directory path
        printf("%s/%s\n", basePath, dp->d_name);

        // Construct new path for directories and check if it is a directory
        snprintf(path, sizeof(path), "%s/%s", basePath, dp->d_name);
        struct stat statbuf;
        stat(path, &statbuf);
        if (S_ISDIR(statbuf.st_mode)) {
            listFiles(path);
        }
    }
    closedir(dir);
}

int main() {
    char *basePath = ".";
    listFiles(basePath);
    return 0;
}

Explanation:

  1. The function listFiles() takes a directory path (basePath) as its argument.
  2. opendir() is used to open the directory. If it fails (returns NULL), the function exits.
  3. The while loop with readdir() iterates over each entry in the directory.
  4. The strcmp() checks ensure that the special directories "." and ".." are skipped.
  5. The printf() statement prints the full path of the current file or directory.
  6. The snprintf() function constructs the new path for each entry.
  7. stat() retrieves information about the file; if the entry is a directory (S_ISDIR()), the function calls itself recursively.
  8. Finally, closedir() closes the directory stream once all entries have been processed.

Output:

./file1.txt
./subdir
./subdir/file2.txt
...

Example 2: Recursive Directory Listing Using nftw()

In this example, we will use the nftw() function from the <ftw.h> library to traverse directories recursively. The nftw() function simplifies recursive directory traversal by handling the recursion internally.

main.c

</>
Copy
#include <stdio.h>
#include <stdlib.h>
#include <ftw.h>

int display(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf) {
    // Print the full path of the file or directory
    printf("%s\n", fpath);
    return 0; // Continue the tree walk
}

int main() {
    int flags = 0;
    // nftw() walks the file tree starting at the current directory (".")
    nftw(".", display, 20, flags);
    return 0;
}

Explanation:

  1. The display() function is a callback used by nftw(); it receives the path (fpath), file status (sb), a flag (typeflag), and a pointer to an FTW structure (ftwbuf).
  2. The callback simply prints the full path of each file or directory encountered.
  3. In main(), nftw() is called with the starting directory ("."), the callback function display(), a maximum of 20 file descriptors (20), and flag options (flags).
  4. The nftw() function traverses the directory tree recursively and calls display() for every entry found.

Output:

./file1.txt
./subdir
./subdir/file2.txt
...

Conclusion

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

  1. Using opendir() and readdir(): This approach involves manually iterating through directory entries and recursively calling a function to traverse subdirectories.
  2. Using nftw(): This method leverages the nftw() function, which simplifies recursive directory traversal by managing recursion internally.