如何使用Boost Filesystem复制目录? 我尝试过boost :: filesystem :: copy_directory()但只创建目标目录而不复制内容。
答案 0 :(得分:44)
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"));
(Unix)
copyDir(boost::filesystem::path("C:\\Users\\nijansen\\test"), boost::filesystem::path("C:\\Users\\nijansen\\test2"));
(Windows)
据我所知,可能发生的最坏情况是没有任何反应,但我不会做出任何承诺!使用风险自负。
请注意,您要复制的目录不得存在。如果您尝试复制的目录中的目录无法读取(思考权限管理),则会跳过它们,但仍应复制其他目录。
<强>更新强>
重构评论的功能。此外,该函数现在返回成功结果。如果不满足给定目录或源目录中任何目录的要求,它将返回false
,但如果无法复制单个文件则不返回。
答案 1 :(得分:13)
自从C ++ 17以来,随着文件系统被添加到标准中,你不再需要对此操作进行提升。
{{1}}
答案 2 :(得分:10)
我认为这个版本是@nijansen的答案的改进版本。它还支持源和/或目标目录是相对的。
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()
做正确的事情具有不同的文件类型(例如,保留符号链接)。
答案 3 :(得分:0)
这是我根据Doineann的代码使用的非增强版。我使用的是std :: filesystem,但无法使用简单的fs::copy(src, dst, fs::copy_options::recursive);
,因为我想过滤循环中文件扩展名复制的文件。
void CopyRecursive(fs::path src, fs::path dst)
{
//Loop through all the dirs
for (auto dir : fs::recursive_directory_iterator(src))
{
//copy the path's string to store relative path string
std::wstring relstr = dir.path().wstring();
//remove the substring matching the src path
//this leaves only the relative path
relstr.erase(0, std::wstring(src).size());
//combine the destination root path with relative path
fs::path newFullPath = dst / relstr;
//Create dir if it's a dir
if (fs::is_directory(newFullPath))
{
fs::create_directory(newFullPath);
}
//copy the files
fs::copy(dir.path(), newFullPath, fs::copy_options::recursive | fs::copy_options::overwrite_existing);
}
}
relstr.erase(0, std::wstring(src).size());
是在另一个答案中使用的boost :: replace_first()调用的有效的无Boost替代方法