I want to iterate over all files in a directory matching something like somefiles*.txt.
Does boost::filesystem have something built in to
My solution is essentially the same as Julien-L, but encapsulated in the include file it is nicer to use. Implemented using boost::filesystem v3. I guess that something like that is not included in the boost::filesystem directly because it would introduce dependency on boost::regex.
#include "FilteredDirectoryIterator.h"
std::vector< std::string > all_matching_files;
std::for_each(
FilteredDirectoryIterator("/my/directory","somefiles.*\.txt"),
FilteredDirectoryIterator(),
[&all_matching_files](const FilteredDirectoryIterator::value_type &dirEntry){
all_matching_files.push_back(dirEntry.path());
}
);
alternatively use FilteredRecursiveDirectoryIterator for recursive sub directories search:
#include "FilteredDirectoryIterator.h"
std::vector< std::string > all_matching_files;
std::for_each(
FilteredRecursiveDirectoryIterator("/my/directory","somefiles.*\.txt"),
FilteredRecursiveDirectoryIterator(),
[&all_matching_files](const FilteredRecursiveDirectoryIterator::value_type &dirEntry){
all_matching_files.push_back(dirEntry.path());
}
);
FilteredDirectoryIterator.h
#ifndef TOOLS_BOOST_FILESYSTEM_FILTEREDDIRECTORYITERATOR_H_
#define TOOLS_BOOST_FILESYSTEM_FILTEREDDIRECTORYITERATOR_H_
#include "boost/filesystem.hpp"
#include "boost/regex.hpp"
#include
template
class FilteredDirectoryIteratorTmpl
: public std::iterator<
std::input_iterator_tag, typename NonFilteredIterator::value_type
>
{
private:
typedef std::string string;
typedef boost::filesystem::path path;
typedef
std::function<
bool(const typename NonFilteredIterator::value_type &dirEntry)
>
FilterFunction;
NonFilteredIterator it;
NonFilteredIterator end;
const FilterFunction filter;
public:
FilteredDirectoryIteratorTmpl();
FilteredDirectoryIteratorTmpl(
const path &iteratedDir, const string ®exMask
);
FilteredDirectoryIteratorTmpl(
const path &iteratedDir, const boost::regex &mask
);
FilteredDirectoryIteratorTmpl(
const path &iteratedDir,
const FilterFunction &filter
);
//preincrement
FilteredDirectoryIteratorTmpl& operator++() {
for(++it;it!=end && !filter(*it);++it);
return *this;
};
//postincrement
FilteredDirectoryIteratorTmpl operator++(int) {
for(++it;it!=end && !filter(*it);++it);
return FilteredDirectoryIteratorTmpl(it,filter);
};
const boost::filesystem::directory_entry &operator*() {return *it;};
bool operator!=(const FilteredDirectoryIteratorTmpl& other)
{
return it!=other.it;
};
bool operator==(const FilteredDirectoryIteratorTmpl& other)
{
return it==other.it;
};
};
typedef
FilteredDirectoryIteratorTmpl
FilteredDirectoryIterator;
typedef
FilteredDirectoryIteratorTmpl
FilteredRecursiveDirectoryIterator;
template
FilteredDirectoryIteratorTmpl::FilteredDirectoryIteratorTmpl()
: it(),
filter(
[](const boost::filesystem::directory_entry& /*dirEntry*/){return true;}
)
{
}
template
FilteredDirectoryIteratorTmpl::FilteredDirectoryIteratorTmpl(
const path &iteratedDir,const string ®exMask
)
: FilteredDirectoryIteratorTmpl(iteratedDir, boost::regex(regexMask))
{
}
template
FilteredDirectoryIteratorTmpl::FilteredDirectoryIteratorTmpl(
const path &iteratedDir,const boost::regex ®exMask
)
: it(NonFilteredIterator(iteratedDir)),
filter(
[regexMask](const boost::filesystem::directory_entry& dirEntry){
using std::endl;
// return false to skip dirEntry if no match
const string filename = dirEntry.path().filename().native();
return boost::regex_match(filename, regexMask);
}
)
{
if (it!=end && !filter(*it)) ++(*this);
}
template
FilteredDirectoryIteratorTmpl::FilteredDirectoryIteratorTmpl(
const path &iteratedDir, const FilterFunction &filter
)
: it(NonFilteredIterator(iteratedDir)),
filter(filter)
{
if (it!=end && !filter(*it)) ++(*this);
}
#endif