2011-12-21 16 views
22

का उपयोग कर निर्देशिका को कॉपी कैसे कर सकता हूं मैं बूस्ट फाइल सिस्टम का उपयोग कर निर्देशिका कैसे कॉपी कर सकता हूं? मैंने boost :: filesystem :: copy_directory() को बढ़ावा देने की कोशिश की है, लेकिन यह केवल लक्ष्य निर्देशिका बनाता है और सामग्री की प्रतिलिपि नहीं बनाता है।बूस्ट फाइल सिस्टम

+0

बूस्ट :: फाइल सिस्टम :: कॉपी निर्देशिका या फ़ाइलों को समान रूप से कॉपी करेगा। आप एक रिकर्सिव एल्गोरिदम लिख सकते हैं जो निर्देशिका और फ़ाइलों को उसमें उपयोग करने के लिए प्रतिलिपि बनाता है। – nijansen

+1

आह। धन्यवाद। मुझे आश्चर्य है कि यह boost :: फाइल सिस्टम का हिस्सा नहीं है। इसके अलावा मुझे बूस्ट लाइब्रेरी वेबसाइट में कोई भी दस्तावेज नहीं मिला जो अंग्रेजी में कहा गया कि वास्तव में फ़ंक्शन copy_directory क्या करता है। – Ant

उत्तर

40
bool copyDir(
    boost::filesystem::path const & source, 
    boost::filesystem::path const & destination 
) 
{ 
    namespace fs = boost::filesystem; 
    try 
    { 
     // Check whether the function call is valid 
     if(
      !fs::exists(source) || 
      !fs::is_directory(source) 
     ) 
     { 
      std::cerr << "Source directory " << source.string() 
       << " does not exist or is not a directory." << '\n' 
      ; 
      return false; 
     } 
     if(fs::exists(destination)) 
     { 
      std::cerr << "Destination directory " << destination.string() 
       << " already exists." << '\n' 
      ; 
      return false; 
     } 
     // Create the destination directory 
     if(!fs::create_directory(destination)) 
     { 
      std::cerr << "Unable to create destination directory" 
       << destination.string() << '\n' 
      ; 
      return false; 
     } 
    } 
    catch(fs::filesystem_error const & e) 
    { 
     std::cerr << e.what() << '\n'; 
     return false; 
    } 
    // Iterate through the source directory 
    for(
     fs::directory_iterator file(source); 
     file != fs::directory_iterator(); ++file 
    ) 
    { 
     try 
     { 
      fs::path current(file->path()); 
      if(fs::is_directory(current)) 
      { 
       // Found directory: Recursion 
       if(
        !copyDir(
         current, 
         destination/current.filename() 
        ) 
       ) 
       { 
        return false; 
       } 
      } 
      else 
      { 
       // Found file: Copy 
       fs::copy_file(
        current, 
        destination/current.filename() 
       ); 
      } 
     } 
     catch(fs::filesystem_error const & e) 
     { 
      std:: cerr << e.what() << '\n'; 
     } 
    } 
    return true; 
} 

उपयोग:

copyDir(boost::filesystem::path("/home/nijansen/test"), boost::filesystem::path("/home/nijansen/test_copy")); (यूनिक्स)

copyDir(boost::filesystem::path("C:\\Users\\nijansen\\test"), boost::filesystem::path("C:\\Users\\nijansen\\test2")); (विंडोज़)

जहां तक ​​मैं देख रहा हूँ, सबसे खराब है कि हो सकता है कुछ भी नहीं होता है कि है, लेकिन मैं जीता कुछ भी वादा नहीं करता! अपने जोखिम पार इस्तेमाल करें।

कृपया ध्यान दें कि जिस निर्देशिका में आप कॉपी कर रहे हैं वह मौजूद नहीं होना चाहिए। यदि निर्देशिका में निर्देशिकाएं जो आप प्रतिलिपि बनाने का प्रयास कर रहे हैं, उन्हें पढ़ा नहीं जा सकता है (विचार अधिकार प्रबंधन), उन्हें छोड़ दिया जाएगा, लेकिन अन्य लोगों को अभी भी कॉपी किया जाना चाहिए।

अद्यतन

समारोह टिप्पणी करने के लिए संबंधित पुनर्स्थापन। इसके अलावा फ़ंक्शन अब सफलता परिणाम देता है। यह false लौटाएगा यदि दिए गए निर्देशिकाओं या स्रोत निर्देशिका के भीतर कोई निर्देशिका पूरी नहीं की जाती है, लेकिन यदि कोई फ़ाइल कॉपी नहीं की जा सकती है।

+7

यदि आप सी ++ का उपयोग करते हैं, तो 'fprintf' और 'stderr' के बजाय' std :: cerr' का उपयोग करना चाहिए। और, चूंकि यह बूस्ट है। फाइल सिस्टम, आपको 'std :: string' के बजाय' boost :: path' का उपयोग करना चाहिए। –

+0

सुझावों के लिए धन्यवाद, मैंने तदनुसार फ़ंक्शन में सुधार किया। – nijansen

+3

ध्यान दें कि आपको अभी भी उस चीज़ से सावधान रहना होगा कि आप कहां कॉपी कर रहे हैं। यदि आप 'copyDir (boost :: filesystem :: path ("।") चलाते हैं, boost :: filesystem :: path ("test"))', यह तब तक स्वयं की प्रतिलिपि बनायेगा जब तक कि इसे समाप्त नहीं किया जाता है क्योंकि पथ की लंबाई सीमा से अधिक है, या आप डिस्क स्पेस से बाहर हो जाते हैं। – nijansen

6

मैं इस संस्करण को @ निजांसेन के उत्तर के संस्करण में सुधार के रूप में देखता हूं। यह स्रोत होने के लिए स्रोत और/या गंतव्य निर्देशिका का भी समर्थन करता है।

namespace fs = boost::filesystem; 

void copyDirectoryRecursively(const fs::path& sourceDir, const fs::path& destinationDir) 
{ 
    if (!fs::exists(sourceDir) || !fs::is_directory(sourceDir)) 
    { 
     throw std::runtime_error("Source directory " + sourceDir.string() + " does not exist or is not a directory"); 
    } 
    if (fs::exists(destinationDir)) 
    { 
     throw std::runtime_error("Destination directory " + destinationDir.string() + " already exists"); 
    } 
    if (!fs::create_directory(destinationDir)) 
    { 
     throw std::runtime_error("Cannot create destination directory " + destinationDir.string()); 
    } 

    for (const auto& dirEnt : fs::recursive_directory_iterator{sourceDir}) 
    { 
     const auto& path = dirEnt.path(); 
     auto relativePathStr = path.string(); 
     boost::replace_first(relativePathStr, sourceDir.string(), ""); 
     fs::copy(path, destinationDir/relativePathStr); 
    } 
} 

मुख्य अंतर वापसी मान के स्थान पर अपवाद हैं, recursive_directory_iterator और boost::replace_first के उपयोग इटरेटर पथ के आम हिस्सा है, और पट्टी (सिमलिंक संरक्षण विभिन्न फ़ाइल प्रकारों के साथ सही काम करने के लिए boost::filesystem::copy() पर भरोसा, उदाहरण के लिए)।

+0

+1 बुलियन रिटर्न मानों पर पूर्ववर्ती अपवादों के लिए +1। इसके अलावा, relatedPathStr को path.lexically_relative (sourceDir) का उपयोग करके गणना की जा सकती है, जो boost :: replace_first से पढ़ने के लिए आसान हो सकता है। – Philippe

2

अब आपको उस कार्य के लिए बढ़ावा की आवश्यकता नहीं है क्योंकि इसकी फाइल सिस्टम लाइब्रेरी को C++ std में शामिल किया गया है। std::filesystem::copy

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

int main() 
{ 
    fs::path source = "path/to/source/folder"; 
    fs::path target = "path/to/target/folder"; 

    try { 
     fs::copy(source, target, fs::copy_options::recursive); 
    } 
    catch (std::exception& e) { // Not using fs::filesystem_error since std::bad_alloc can throw too. 
     // Handle exception or use error code overload of fs::copy. 
    } 
} 

के अलावा भी std::filesystem::copy_options देखें।

+0

बहुत धन्यवाद रोई। मुझे आशा है कि आगंतुक आपका जवाब देखेंगे। – Ant

+0

नोट यह सी ++ 17 में आईएसओ सी ++ में जोड़ा गया था। –

संबंधित मुद्दे