recursive folder scanning in c++
Solution 1
See man ftw
for a simple "file tree walk". I also used fnmatch
in this example.
#include <ftw.h>
#include <fnmatch.h>
static const char *filters[] = {
"*.jpg", "*.jpeg", "*.gif", "*.png"
};
static int callback(const char *fpath, const struct stat *sb, int typeflag) {
/* if it's a file */
if (typeflag == FTW_F) {
int i;
/* for each filter, */
for (i = 0; i < sizeof(filters) / sizeof(filters[0]); i++) {
/* if the filename matches the filter, */
if (fnmatch(filters[i], fpath, FNM_CASEFOLD) == 0) {
/* do something */
printf("found image: %s\n", fpath);
break;
}
}
}
/* tell ftw to continue */
return 0;
}
int main() {
ftw(".", callback, 16);
}
(Not even compile-tested, but you get the idea.)
This is much simpler than dealing with DIRENT
s and recursive traversal yourself.
For greater control over traversal, there's also fts
. In this example, dot-files (files and directories with names starting with ".") are skipped, unless explicitly passed to the program as a starting point.
#include <fts.h>
#include <string.h>
int main(int argc, char **argv) {
char *dot[] = {".", 0};
char **paths = argc > 1 ? argv + 1 : dot;
FTS *tree = fts_open(paths, FTS_NOCHDIR, 0);
if (!tree) {
perror("fts_open");
return 1;
}
FTSENT *node;
while ((node = fts_read(tree))) {
if (node->fts_level > 0 && node->fts_name[0] == '.')
fts_set(tree, node, FTS_SKIP);
else if (node->fts_info & FTS_F) {
printf("got file named %s at depth %d, "
"accessible via %s from the current directory "
"or via %s from the original starting directory\n",
node->fts_name, node->fts_level,
node->fts_accpath, node->fts_path);
/* if fts_open is not given FTS_NOCHDIR,
* fts may change the program's current working directory */
}
}
if (errno) {
perror("fts_read");
return 1;
}
if (fts_close(tree)) {
perror("fts_close");
return 1;
}
return 0;
}
Again, it's neither compile-tested nor run-tested, but I thought I'd mention it.
Solution 2
Boost.Filesystem allows you to do that. Check out the docs!
EDIT:
If you are using Linux and you don't want to use Boost, you will have to use the Linux native C functions. This page shows many examples on how to do just that.
Solution 3
You can also use glob/globfree.
Stulli
Updated on December 20, 2020Comments
-
Stulli over 3 years
I want to scan a directory tree and list all files and folders inside each directory. I created a program that downloads images from a webcamera and saves them locally. This program creates a filetree based on the time the picture is downloaded. I now want to scan these folders and upload the images to a webserver but I´m not sure how I can scan the directories to find the images. If anyone could post some sample code it would be very helpful.
edit: I´m running this on an embedded linux system and don´t want to use boost
-
ephemient about 15 yearsEasier than reading directories and performing matches yourself, but still not recursive. Granted, using GLOB_ONLYDIR means that you could avoid dealing with DIRENTs altogether, but it's still not as handy as ftw, and purely name-based traversals are racy.
-
Hortitude over 14 yearsThe FTS sample worked great. The only changes I had to make were "ftsread" --> "fts_read" and I had to cast the result of fts_read to (FTSENT*). I would have thought finding code like this would have been easier on the web, but this was definitely the cleanest example I found. Thanks!
-
darron about 11 yearsValues for fts_info are not single bits... options FTS_D through FTS_W are defined as sequential values 1 through 14. It is probably confusing to some to have the code as "& FTS_F" without a comment explaining what's up. It's POSSIBLE people intended to grab FTS_F, FTS_INIT, FTS_NS, FTS_NSOK, FTS_SL, FTS_SLNONE, and FTS_W here... but FTS_NS or FTS_NSOK would be a bit odd. Also, I see code on the web doing "& FTS_D", which is almost certainly not what they intended (gets FTS_ERR, FTS_DEFAULT).