c++ 如何使用Boost Filesystem复制目录

mjqavswn  于 2023-03-20  发布在  其他
关注(0)|答案(5)|浏览(458)

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

bogh5gae

bogh5gae1#

这是我使用的基于Doineann代码的非Boost版本,我使用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替换

kzmpq1sx

kzmpq1sx2#

使用Boost库将一个目录的内容复制到另一个目录的C++示例程序:

#include <boost/filesystem.hpp>

namespace fs = boost::filesystem;

int main()
{
    fs::path source_dir("path/to/source/directory");
    fs::path destination_dir("path/to/destination/directory");
    try
    {
        // Check if source directory exists
        if (!fs::exists(source_dir))
        {
            std::cerr << "Source directory does not exist." << std::endl;
            return 1;
        }
        // Check if destination directory exists, if not create it
        if (!fs::exists(destination_dir))
        {
            fs::create_directory(destination_dir);
        }
        // Iterate over all the files in the source directory
        for (fs::directory_iterator file(source_dir); file != fs::directory_iterator(); ++file)
        {
            // Copy file to destination directory
            fs::copy_file(file->path(), destination_dir / file->path().filename(), fs::copy_option::overwrite_if_exists);
        }
    }
    catch (fs::filesystem_error const& e)
    {
        std::cerr << "Error copying directory: " << e.what() << std::endl;
    }
    return 0;
}

在这个程序中,我们使用Boost的文件系统库来访问和操作文件和目录。程序检查源目录是否存在,如果不存在则创建目标目录。然后迭代源目录中的所有文件,并使用fs::copy_file()函数将每个文件复制到目的目录。fs::copy_option::overwrite_if_exists标志用于覆盖目标目录中的现有文件。

q0qdq0h2

q0qdq0h23#

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,但如果无法复制单个文件,则不会返回false

ljo96ir5

ljo96ir54#

从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.
    }
}

另请参见std::filesystem::copy_options

fnx2tebb

fnx2tebb5#

我认为这个版本是@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_iteratorboost::replace_first剥离迭代器路径的公共部分,以及依赖boost::filesystem::copy()对不同的文件类型做正确的事情(例如,保留符号链接)。

相关问题