Summary
In this post, I will introduce how to get a vector of files in a directory in C++. Instead of filesystem
in boost or C++ 17, this method is purely based on C++ 11 and Unix platforms.
Details
The following codes are self-explained.
// safe path join in unix-based system
string path_join(const string& p1, const string& p2) {
char sep = '/';
string tmp = p1;
if (p1[p1.size() - 1] != sep) { // Need to add a
tmp += sep; // path separator
return(tmp + p2);
}
else
return(p1 + p2);
}
// make sure files are either directories or files
// dfs to get all files
void get_files(const string &dir, vector<string> &all_files) {
shared_ptr<DIR> directory_ptr(opendir(dir.c_str()), [](DIR* dir){ dir && closedir(dir); });
struct dirent *dirent_ptr;
if (!directory_ptr) {
cout << "Error opening : " << strerror(errno) << dir << std::endl;
return;
}
while ((dirent_ptr = readdir(directory_ptr.get())) != nullptr) {
// get all the files in a directory, ignoring ".." and "."
if (strcmp(dirent_ptr->d_name, ".") != 0 && strcmp(dirent_ptr->d_name, "..") != 0) {
string curr_path = path_join(dir, string(dirent_ptr->d_name));
// if it is a regular file
if (dirent_ptr->d_type == DT_REG) {
all_files.push_back(curr_path);
} else { // a directory
get_files(curr_path, all_files);
}
}
}
}
shared_ptr
shared_ptr<DIR> directory_ptr(opendir(dir.c_str()), [](DIR* dir){ dir && closedir(dir); });
I will introduce smart_ptr
in another post. The syntax here of shared_ptr
basically passes a initial pointer whose type is DIR
(a directory stream) and a lambda function which defines how to safely delete the pointer (close the directory stream).
See opendir and closedir.
dirent and readdir
See readdir. On Linux, the dirent structure is defined as follows:
struct dirent {
ino_t d_ino; /* inode number */
off_t d_off; /* offset to the next dirent */
unsigned short d_reclen; /* length of this record */
unsigned char d_type; /* type of file; not supported
by all file system types */
char d_name[256]; /* filename */
};
file type
We can use variable members d_type
in dirent
to see if the current file is a regular file or a diretory.