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:
- POSIX/Unix Approach (
opendir,readdir,closedir) - Windows-Specific API (
FindFirstFile,FindNextFile) - 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 additionalstatcall 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 populatesfindDatawith the first file.FindNextFile(handle, &findData): UpdatesfindDatawith 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
Filtering
- Often, you’ll want to skip
.and..or filter out subdirectories. On Unix, useentry->d_typeorstat. On Windows, checkfindData.dwFileAttributesforFILE_ATTRIBUTE_DIRECTORY. - In C++17,
fs::is_directory(entry.status())or similar calls are available.
- Often, you’ll want to skip
Error Handling
- Always handle failures (e.g., cannot open directory, invalid path).
- Check
errnoon POSIX orGetLastError()on Windows for specific error codes.
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
FindFirstFileWwith 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:
Grokking Data Structures & Algorithms for Coding Interviews
Build a robust foundation in memory handling, arrays, lists, and more, giving you confidence when working at a low level in C/C++.Grokking the Coding Interview: Patterns for Coding Questions
Learn to identify and apply recurring problem-solving patterns—vital for quickly handling directory traversal, file processing, and various other code challenges.
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.