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.
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 additionalstat
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 populatesfindData
with the first file.FindNextFile(handle, &findData)
: UpdatesfindData
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
-
Filtering
- Often, you’ll want to skip
.
and..
or filter out subdirectories. On Unix, useentry->d_type
orstat
. On Windows, checkfindData.dwFileAttributes
forFILE_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
errno
on 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
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:
-
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.