Can I use a mask to iterate files in a directory with Boost?

后端 未结 7 1149
既然无缘
既然无缘 2020-11-27 03:51

I want to iterate over all files in a directory matching something like somefiles*.txt.

Does boost::filesystem have something built in to

7条回答
  •  旧时难觅i
    2020-11-27 04:08

    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
    

提交回复
热议问题