如何使用Boost Filesystem复制目录

Ant*_*Ant 26 c++ filesystems directory boost copy

如何使用Boost Filesystem复制目录?我尝试过boost :: filesystem :: copy_directory(),但只创建目标目录而不复制内容.

nij*_*sen 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;
}
Run Code Online (Sandbox Code Playgroud)

用法:

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")); (视窗)

据我所知,可能发生的最坏情况是没有任何反应,但我不会做出任何承诺!使用风险由您自己承担.

请注意,您要复制到的目录不得存在.如果您尝试复制的目录中的目录无法读取(思考权限管理),则会跳过它们,但仍应复制其他目录.

更新

重构了评论的功能.此外,该函数现在返回成功结果.false如果不满足给定目录或源目录中任何目录的要求,它将返回,但如果无法复制单个文件则不会返回.

  • 如果你使用C++,应该使用`std :: cerr`而不是`fprintf`和`stderr`.而且,由于这是Boost.Filesystem,你应该使用`boost :: path`而不是`std :: string`. (8认同)
  • 请注意,您仍然需要小心在哪里复制.如果你运行`copyDir(boost :: filesystem :: path("."),boost :: filesystem :: path("test"))`,它将自我复制,直到它被终止,因为路径长度超过了限制,或者你的磁盘空间不足. (3认同)
  • 非常感谢nijansen,非常适合我正在做的事情.我正在将一个定义良好且已知的文件夹复制到另一个位置,因此我不需要担心任何特殊情况.我仍然对copy_directory不复制内容或至少有复制内容的选项感到惊讶. (2认同)

Roi*_*ton 15

从C++ 17开始,随着文件系统被添加到标准中,您不再需要对此操作进行提升.

使用 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.
    }
}
Run Code Online (Sandbox Code Playgroud)

另见std::filesystem::copy_options.

  • 请注意,这已添加到C++ 17中的ISO C++中. (2认同)

小智 11

我认为这个版本是@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);
    }
}
Run Code Online (Sandbox Code Playgroud)

主要的区别是异常而不是返回值,使用recursive_directory_iteratorboost::replace_first去除迭代器路径的公共部分,并依赖于boost::filesystem::copy()使用不同的文件类型做正确的事情(例如,保留符号链接).