Search code examples
c++boostfilesystemsboost-filesystem

C++: How do I ignore the first directory path when comparing paths in boost::filesystem?


I'm trying to compare two directories and find what files are different inside. So I'm using a boost::filesystem::recursive_directory_iterator to add all contents of each directory to respective vectors. Then I sort each vector alphabetically and start comparing paths. The problem is it's including the 'base' path and I don't want that, example:

Version1/Assets/info.txt

Version2/Assets/info.txt

Those paths are comparing different, but I want them to compare the same. To clarify, I'm not even checking the binaries yet, just the path name so far. I'd to compare them like this:

/Assets/info.txt

I've been browsing through the boost documentation for a couple hours and I'm convinced there must be an elegant solution for my problem. I realize I could have solved this a while ago by getting a substring of what I want, but there must be a less ugly way.


Solution

  • The boost::filesystem::recursive_directory_iterator has a path() property that you can query. You can then use the following decomposition methods available for boost::filesystem::path to manually build the path to compare:

    path  root_path() const; 
    path  root_name() const;         // returns 0 or 1 element path
    path  root_directory() const;    // returns 0 or 1 element path
    path  relative_path() const;
    path  parent_path() const;
    path  filename() const;          // returns 0 or 1 element path
    path  stem() const;              // returns 0 or 1 element path
    path  extension() const;         // returns 0 or 1 element path
    

    For example you can rollout a version of stripping the root as follows:

    #include <iostream>
    #include <boost/filesystem.hpp>
    
    boost::filesystem::path strip_root(const boost::filesystem::path& p) {
        const boost::filesystem::path& parent_path = p.parent_path();
        if (parent_path.empty() || parent_path.string() == "/")
            return boost::filesystem::path();
        else
            return strip_root(parent_path) / p.filename();
    }
    
    int main() {
        std::cout << strip_root("/a") << std::endl;
        std::cout << strip_root("/a/b") << std::endl;
        std::cout << strip_root("/a/b/c") << std::endl;
        std::cout << strip_root("/a/b.dir/c.ext") << std::endl;    
    }
    // Output:
    ""
    "b"
    "b/c"
    "b.dir/c.ext"