2012-04-16 14 views
24

boost::filesystem लाइब्रेरी के कौन से तरीके मुझे किसी अन्य पथ से संबंधित पथ प्राप्त करने में मदद कर सकते हैं?बढ़ावा :: फाइल सिस्टम को सापेक्ष पथ

मेरे पास पथ /home/user1/Downloads/Books और पथ /home/user1/ है। अब मैं Downloads/Books पथ प्राप्त करना चाहता हूं।

+0

सब और विफल रहता है, निरपेक्ष तार करने के लिए दोनों को बदलने और दूसरे से सबस्ट्रिंग। –

+0

बूस्ट के नए संस्करणों में ** बहुत सरल ** इसका उत्तर दिया गया है, [नीचे दिया गया] [https://stackoverflow.com/a/37715252/16287) –

उत्तर

14

एक कड़ी से लिया टिकट निकोल से जुड़ा हुआ अनुसरण करके प्राप्त:

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; 
+1

उस नमूना कॉल में 'make_relative' योग्यता प्राप्त करने की कोई आवश्यकता नहीं है। यह गलत हो सकता है (दिया गया कोड ऐसा नहीं लगता है कि यह 'boost :: फाइल सिस्टम' में 'make_relative' डालता है) और यदि यह सही है, तो यह एडीएल के कारण अनावश्यक है। – MSalters

6

अफसोस की बात है, ऐसा फ़ंक्शन Boost.Filesystem में मौजूद नहीं है। It has been requested, लेकिन वे परवाह नहीं है।

आपको मूल रूप से इसे मैन्युअल रूप से करना होगा।

बूस्ट। फ़ाइल सिस्टम 1.60 the relative function जो इसे संभालने के लिए उपयोग किया जा सकता है।

+1

असल में, पैच को किसी कारण से अस्वीकार कर दिया गया था (उपयोग संलग्न)। –

+1

@ महमूद अल-कुडसी: मैंने एक फीचर अनुरोध से जुड़ा हुआ है। उस अनुरोध पर एक टिप्पणी में एक पैच जुड़ा हुआ है, लेकिन यह अनुरोध का * भाग * नहीं है। –

+0

आप सही हैं। शायद कुछ और टिप्पणियां मददगार होंगी? :) –

1

स्वीकार किए जाते हैं जवाब के कोड काम नहीं करता। यह

namespace boost { namespace filesystem { 

template <> path& path::append<path::iterator>(path::iterator begin, 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; 
} 

} } // namespace boost::filesystem 
17

प्रदान किए गए उत्तरों में कोड प्रत्येक पंक्ति पर काफी लंबा है। यह मानते हुए कि आप namespace fs = boost::filesystem; लिखा था तो इस कोड को आप जिस तरह से ज्यादातर हो जाता है और मेरे लिए पढ़ने में आसान लग रहा है:

static fs::path relativeTo(fs::path from, 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. 
    fs::path::const_iterator fromIter = from.begin(); 
    fs::path::const_iterator 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) 
    fs::path finalPath; 
    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; 
} 
+0

यह मेरे लिए काम किया –

+2

यह अन्य उत्तरों की तुलना में बहुत बेहतर दिखता है। –

20

boost के नए संस्करण में (1.60 में शुरू होने वाले), तो आपको boost::filesystem::relative उपयोग कर सकते हैं। (See the documentation here.)

#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; 
} 
संबंधित मुद्दे