Search code examples
c++boostfilesystemsboost-filesystem

boost::filesystem get relative path


What methods of the boost::filesystem library can help me to get a path relative to another path?

I have a path /home/user1/Downloads/Books and a path /home/user1/. Now I want to get a path Downloads/Books.


Solution

  • Taken from a link found by following the ticket Nicol linked to:

    template < >
        path& path::append< typename path::iterator >( typename path::iterator begin, typename path::iterator end, const codecvt_type& cvt)
        { 
            for( ; begin != end ; ++begin )
                *this /= *begin;
            return *this;
        }
        // Return path when appended to a_From will resolve to same as a_To
        boost::filesystem::path make_relative( boost::filesystem::path a_From, boost::filesystem::path a_To )
        {
            a_From = boost::filesystem::absolute( a_From ); a_To = boost::filesystem::absolute( a_To );
            boost::filesystem::path ret;
            boost::filesystem::path::const_iterator itrFrom( a_From.begin() ), itrTo( a_To.begin() );
            // Find common base
            for( boost::filesystem::path::const_iterator toEnd( a_To.end() ), fromEnd( a_From.end() ) ; itrFrom != fromEnd && itrTo != toEnd && *itrFrom == *itrTo; ++itrFrom, ++itrTo );
            // Navigate backwards in directory to reach previously found base
            for( boost::filesystem::path::const_iterator fromEnd( a_From.end() ); itrFrom != fromEnd; ++itrFrom )
            {
                if( (*itrFrom) != "." )
                    ret /= "..";
            }
            // Now navigate down the directory branch
            ret.append( itrTo, a_To.end() );
            return ret;
        }
    

    Stick that in a header file and it should do what you want.

    Sample call:

    boost::filesystem::path a("foo/bar"), b("foo/test/korv.txt");
    std::cout << make_relative( a, b ).string() << std::endl;