Explain

How can I get the list of files in a directory using C or C++?

Several approaches exist for enumerating files in a directory, depending on your platform and which libraries you’re allowed to use. Below are three common methods:

  1. POSIX/Unix Approach (opendir, readdir, closedir)
  2. Windows-Specific API (FindFirstFile, FindNextFile)
  3. C++17 std::filesystem (portable across modern compilers)

1. POSIX/Unix Approach: opendir / readdir / closedir

Works on: Linux, macOS, and other Unix-like systems.

Recommended Courses

Example

#include <stdio.h>
#include <dirent.h>
#include <string.h>

int main(void) {
    const char *path = "."; // current directory
    DIR *dir = opendir(path);
    if (!dir) {
        perror("opendir");
        return 1;
    }

    struct dirent *entry;
    while ((entry = readdir(dir)) != NULL) {
        // Skip "." and ".."
        if (strcmp(entry->d_name, ".") == 0 ||
            strcmp(entry->d_name, "..") == 0) {
            continue;
        }

        printf("%s\n", entry->d_name);
    }

    closedir(dir);
    return 0;
}
  • Key Functions:

    • opendir(path): Opens a directory stream.
    • readdir(dir): Returns a pointer to the next directory entry (struct dirent).
    • closedir(dir): Closes the directory stream.
  • Check entry->d_type (if supported) to see if it’s a file, directory, etc. Alternatively, do an additional stat call to query file info.

2. Windows-Specific API: FindFirstFile / FindNextFile

Works on: Microsoft Windows.
Header: <windows.h>

Example

#include <windows.h>
#include <tchar.h>   // For _T() macro (if you use it)
#include <iostream>

int main() {
    WIN32_FIND_DATA findData;
    HANDLE hFind = INVALID_HANDLE_VALUE;

    // Build the search pattern (e.g., "C:\\path\\to\\directory\\*")
    const char* directory = "C:\\path\\to\\directory\\*";
    hFind = FindFirstFile(directory, &findData);

    if (hFind == INVALID_HANDLE_VALUE) {
        std::cerr << "FindFirstFile failed.\n";
        return 1;
    }

    do {
        // Skip "." and ".."
        if (strcmp(findData.cFileName, ".") == 0 ||
            strcmp(findData.cFileName, "..") == 0) {
            continue;
        }

        std::cout << findData.cFileName << "\n";
    } while (FindNextFile(hFind, &findData) != 0);

    FindClose(hFind);
    return 0;
}
  • Key Functions:
    • FindFirstFile(searchPattern, &findData): Returns a handle and populates findData with the first file.
    • FindNextFile(handle, &findData): Updates findData with the next file until no more files are found.
    • FindClose(handle): Closes the search handle.

3. C++17 std::filesystem (Portable)

Works on: Systems with C++17 or later support, including modern Windows, Linux, macOS compilers.

Example

#include <iostream>
#include <filesystem>  // C++17
namespace fs = std::filesystem;

int main() {
    std::string path = ".";
    try {
        for (const auto &entry : fs::directory_iterator(path)) {
            std::cout << entry.path().filename().string() << "\n";
        }
    } catch (const fs::filesystem_error& e) {
        std::cerr << "Error: " << e.what() << "\n";
        return 1;
    }

    return 0;
}
  • Advantages:
    • Cross-platform (where C++17 filesystem is supported).
    • Provides higher-level operations (checking file type, size, etc.) via fs::directory_entry.

Notes & Tips

  1. Filtering

    • Often, you’ll want to skip . and .. or filter out subdirectories. On Unix, use entry->d_type or stat. On Windows, check findData.dwFileAttributes for FILE_ATTRIBUTE_DIRECTORY.
    • In C++17, fs::is_directory(entry.status()) or similar calls are available.
  2. Error Handling

    • Always handle failures (e.g., cannot open directory, invalid path).
    • Check errno on POSIX or GetLastError() on Windows for specific error codes.
  3. Large Directories

    • Directories with many files require a loop reading all entries.
    • On Windows, you might need to handle long paths or Unicode file names (e.g., using FindFirstFileW with wide strings).

Want to Master System-Level Programming?

For a deeper dive into how operating systems handle files, directories, memory, and beyond—and to prepare for tough technical interviews—two recommended courses from DesignGurus.io:

By getting comfortable with the native APIs (opendir, readdir, or FindFirstFile) or the modern C++17 std::filesystem approach, you’ll be equipped to handle file-system-related tasks robustly and efficiently in your C/C++ projects.