33

ライブラリのどのメソッドを使用すると、boost::filesystem別のパスからの相対パスを取得できますか?

私はパス/home/user1/Downloads/Booksとパスを持っています/home/user1/。今私はパスを取得したいDownloads/Books

4

6 に答える 6

41

の新しいバージョンboost(1.60 以降) では、 を使用できますboost::filesystem::relative(こちらのドキュメントを参照してください。)

#include <boost/filesystem.hpp>
#include <iostream>
namespace fs = boost::filesystem;

int main()
{
    fs::path parentPath("/home/user1/");
    fs::path childPath("/home/user1/Downloads/Books");
    fs::path relativePath = fs::relative(childPath, parentPath);
    std::cout << relativePath << std::endl;
}
于 2016-06-09T00:53:07.680 に答える
21

提供された回答のコードは、各行で非常に長いです。あなたが書いたと仮定するとnamespace fs = boost::filesystem;、このコードはほとんどの場合に役立ち、私には読みやすく見えます:

    auto relativeTo( const fs::path& from, const fs::path& to )
    {
       // Start at the root path and while they are the same then do nothing then when they first
       // diverge take the entire from path, swap it with '..' segments, and then append the remainder of the to path.
       auto fromIter = from.begin();
       auto toIter = to.begin();

       // Loop through both while they are the same to find nearest common directory
       while( fromIter != from.end() && toIter != to.end() && *toIter == *fromIter )
       {
          ++toIter;
          ++fromIter;
       }

       // Replace from path segments with '..' (from => nearest common directory)
       auto finalPath = fs::path{};
       while( fromIter != from.end() )
       {
          finalPath /= "..";
          ++fromIter;
       }

       // Append the remainder of the to path (nearest common directory => to)
       while( toIter != to.end() )
       {
          finalPath /= *toIter;
          ++toIter;
       }

       return finalPath;
    }
于 2015-03-23T22:21:15.667 に答える
15

ニコルがリンクしているチケットをたどって見つけたリンクから取得:

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;
    }

それをヘッダーファイルに貼り付けると、必要な処理が実行されます。

サンプルコール:

boost::filesystem::path a("foo/bar"), b("foo/test/korv.txt");
std::cout << make_relative( a, b ).string() << std::endl;
于 2012-04-16T00:55:04.257 に答える
6

残念ながら、Boost.Filesystem にはそのような機能はありません。リクエストされましたが、気にしていないようです。

基本的に手動で行う必要があります。

Boost.Filesystem 1.60 では、これを処理するために使用できる関数が追加されましrelative

于 2012-04-16T00:41:21.953 に答える
2

C++17 以降、この問題の解決策は、存在するパスにはstd::filesystem::relativeを使用し、存在しない可能性のあるパスにはstd::filesystem::path::lexically_relativeを使用することです。

#include <iostream>
#include <filesystem>
namespace fs = std::filesystem;

fs::path path("/home/user1/Downloads/Books");
fs::path base("/home/user1/");
std::cout << fs::relative(path, base) << '\n';
std::cout << path.lexically_relative(base) << '\n';

これは印刷します

"Downloads/Books"
"Downloads/Books"
于 2021-12-01T16:13:22.560 に答える