Tag Archives: POSIX

How to list the Files in a Directory in C++

Introduction

Imagine that we want to populate a vector with the names of the files in a directory with a read_directory() function like this:

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <iterator>

typedef std::vector<std::string> stringvec;

int main()
{
    stringvec v;
    read_directory(".", v);
    std::copy(v.begin(), v.end(),
         std::ostream_iterator<std::string>(std::cout, "\n"));
}

There are 4 methods we can use:

  1. Use boost::filesystem::directory_iterator
  2. Use std::filesystem::directory_iterator (C++17)
  3. Use opendir()/readdir()/closedir() (POSIX)
  4. Use FindFirstFile()/FindNextFile()/FindClose() (Windows)

Method 1: Use boost::filesystem

#include <boost/filesystem.hpp>

struct path_leaf_string
{
    std::string operator()(const boost::filesystem::directory_entry& entry) const
    {
        return entry.path().leaf().string();
    }
};

void read_directory(const std::string& name, stringvec& v)
{
    boost::filesystem::path p(name);
    boost::filesystem::directory_iterator start(p);
    boost::filesystem::directory_iterator end;
    std::transform(start, end, std::back_inserter(v), path_leaf_string());
}

Reference: Boost Filesystem Library Version 3

Method 2: Use std::filesystem (C++17)

#include <filesystem>

struct path_leaf_string
{
    std::string operator()(const std::filesystem::directory_entry& entry) const
    {
        return entry.path().leaf().string();
    }
};

void read_directory(const std::string& name, stringvec& v)
{
    std::filesystem::path p(name);
    std::filesystem::directory_iterator start(p);
    std::filesystem::directory_iterator end;
    std::transform(start, end, std::back_inserter(v), path_leaf_string());
}

Method 3: Use opendir()/readdir()/closedir() (POSIX)

#include <sys/types.h>
#include <dirent.h>

void read_directory(const std::string& name, stringvec& v)
{
    DIR* dirp = opendir(name.c_str());
    struct dirent * dp;
    while ((dp = readdir(dirp)) != NULL) {
        v.push_back(dp->d_name);
    }
    closedir(dirp);
}

Reference: readdir – The Open Group

Method 4: Use FindFirstFile()/FindNextFile()/FindClose() (Windows)

#include <windows.h>

void read_directory(const std::string& name, stringvec& v)
{
    std::string pattern(name);
    pattern.append("\\*");
    WIN32_FIND_DATA data;
    HANDLE hFind;
    if ((hFind = FindFirstFile(pattern.c_str(), &data)) != INVALID_HANDLE_VALUE) {
        do {
            v.push_back(data.cFileName);
        } while (FindNextFile(hFind, &data) != 0);
        FindClose(hFind);
    }
}

Reference: FindFirstFile function

Related

How to read a file into a string in C++