Introduction
When working with file systems in C or C++, you may often need to list all files within a specific directory. This task can be accomplished using various methods, each suitable for different versions of the language and operating systems. Below, we’ll explore multiple approaches to listing files in a directory, ranging from standard library facilities introduced in modern C++ to platform-specific solutions available in C.
Using std::filesystem
in Modern C++
For developers working with C++17 or later, the <filesystem>
header provides an elegant and cross-platform way of managing file systems. The std::filesystem
namespace offers classes such as directory_iterator
and recursive_directory_iterator
, which allow you to iterate over files and directories.
Example: Listing Files in a Directory
#include <iostream>
#include <string>
#include <filesystem>
namespace fs = std::filesystem;
int main() {
std::string path = "/path/to/directory";
for (const auto& entry : fs::directory_iterator(path)) {
std::cout << entry.path().filename() << std::endl;
}
}
This code iterates over each file in the specified directory and prints its name. The entry.path()
provides a complete path, but entry.path().filename()
is used to retrieve just the file name.
Recursive Listing
For situations where you need to traverse subdirectories as well, use recursive_directory_iterator
:
#include <iostream>
#include <string>
#include <filesystem>
namespace fs = std::filesystem;
int main() {
std::string path = "/path/to/directory";
for (const auto& entry : fs::recursive_directory_iterator(path)) {
if (!fs::is_directory(entry.status())) {
std::cout << entry.path().filename() << std::endl;
}
}
}
This code will recursively list all files, skipping directories themselves in the output.
Using POSIX dirent.h
for UNIX-like Systems
For those working with C or older versions of C++ without <filesystem>
, you can use the POSIX dirent.h
library. This is available natively on UNIX and Linux systems.
Example: Listing Files Using dirent.h
#include <stdio.h>
#include <dirent.h>
int main() {
DIR *dir;
struct dirent *entry;
if ((dir = opendir("/path/to/directory")) != NULL) {
while ((entry = readdir(dir)) != NULL) {
printf("%s\n", entry->d_name);
}
closedir(dir);
} else {
perror("opendir");
return 1;
}
return 0;
}
This C code opens the specified directory and iterates over each entry, printing its name. The dirent
structure provides information about each file or subdirectory.
Using Windows API
For applications targeting Windows platforms, you can use the Win32 API functions like FindFirstFile
, FindNextFile
, and FindClose
.
Example: Listing Files with Win32 API
#include <windows.h>
#include <iostream>
int main() {
WIN32_FIND_DATA findData;
HANDLE hFind = FindFirstFile("C:\\path\\to\\directory\\*.*", &findData);
if (hFind == INVALID_HANDLE_VALUE) {
std::cerr << "Failed to list directory" << std::endl;
return 1;
}
do {
// Skip '.' and '..' directories
if ((findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
(strcmp(findData.cFileName, ".") != 0 && strcmp(findData.cFileName, "..") != 0)) {
std::cout << findData.cFileName << " [Directory]" << std::endl;
} else if (!(findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
std::cout << findData.cFileName << std::endl; // File
}
} while (FindNextFile(hFind, &findData) != 0);
FindClose(hFind);
return 0;
}
This code lists all files and directories in the specified folder. It uses FindFirstFile
to start the search and FindNextFile
to continue iterating through entries.
Using Third-party Libraries for C
If you are constrained to writing pure C programs, consider using a small library like tinydir, which provides a simple API compatible with both POSIX and Windows systems.
Example: Listing Files with Tinydir
#include "tinydir.h"
#include <stdio.h>
int main() {
tinydir_dir dir;
if (tinydir_open(&dir, "/path/to/dir") == -1) {
fprintf(stderr, "Failed to open directory\n");
return 1;
}
while (dir.has_next) {
tinydir_file file;
tinydir_readfile(&dir, &file);
printf("%s", file.name);
if (file.is_dir) {
printf("/");
}
printf("\n");
tinydir_next(&dir);
}
tinydir_close(&dir);
return 0;
}
This example uses tinydir
to iterate through a directory, printing the names of files and directories.
Conclusion
Listing files in a directory is a common task that can be accomplished using different methods depending on your programming language version and target operating system. C++17’s <filesystem>
offers a modern and portable solution, while POSIX dirent.h
and Windows API functions provide platform-specific alternatives for older or C-only projects. For pure C applications, third-party libraries like tinydir offer a lightweight option.