命名空间
变体
操作

std::filesystem::copy

来自 cppreference.cn
 
 
 
定义于头文件 <filesystem>
void copy( const std::filesystem::path& from,
           const std::filesystem::path& to );
(1) (自 C++17)
void copy( const std::filesystem::path& from,

           const std::filesystem::path& to,

           std::error_code& ec );
(2) (自 C++17)
void copy( const std::filesystem::path& from,

           const std::filesystem::path& to,

           std::filesystem::copy_options options );
(3) (自 C++17)
void copy( const std::filesystem::path& from,

           const std::filesystem::path& to,
           std::filesystem::copy_options options,

           std::error_code& ec );
(4) (自 C++17)

复制文件和目录,带有多种选项。

1,2) 默认行为,等同于 (3,4),使用 copy_options::none 作为 options
3,4) 使用 options 指示的复制选项,将文件或目录 from 复制到文件或目录 to。 如果在 copy_options 选项组中的任何一个选项中存在多个选项(即使在 copy_file 组中),则行为未定义。

行为如下:

  • 首先,在执行任何其他操作之前,通过不超过一次调用来获取 from 的类型和权限:
  • 如有必要,通过不超过一次调用来获取 to 的状态:
  • 如果 fromto 具有实现定义的 文件类型,则此函数的效果是实现定义的。
  • 如果 from 不存在,则报告错误。
  • 如果 fromto 是由 std::filesystem::equivalent 确定的同一文件,则报告错误。
  • 如果 fromto 不是常规文件、目录或符号链接,如 std::filesystem::is_other 所确定,则报告错误。
  • 如果 from 是目录,但 to 是常规文件,则报告错误。
  • 如果 from 是符号链接,则
  • 如果 options 中存在 copy_options::skip_symlink,则不执行任何操作。
  • 否则,如果 to 不存在且 options 中存在 copy_options::copy_symlinks,则行为如同 copy_symlink(from, to)
  • 否则,报告错误。
  • 否则,如果 from 是常规文件,则
  • 如果 options 中存在 copy_options::directories_only,则不执行任何操作。
  • 否则,如果 options 中存在 copy_options::create_symlinks,则创建指向 to 的符号链接。 注意: from 必须是绝对路径,除非 to 位于当前目录中。
  • 否则,如果 options 中存在 copy_options::create_hard_links,则创建指向 to 的硬链接。
  • 否则,如果 to 是目录,则行为如同 copy_file(from, to/from.filename(), options) (在目录 to 中创建 from 的文件副本)。
  • 否则,行为如同 copy_file(from, to, options) (复制文件)。
  • 否则,如果 from 是目录且 options 中设置了 copy_options::create_symlinks,则报告错误,错误代码等于 std::make_error_code(std::errc::is_a_directory)
  • 否则,如果 from 是目录且 options 具有 copy_options::recursive 或为 copy_options::none
  • 如果 to 不存在,则首先执行 create_directory(to, from) (使用旧目录属性的副本创建新目录)。
  • 然后,无论 to 已经存在还是刚刚创建,都像通过 for (const std::filesystem::directory_entry& x : std::filesystem::directory_iterator(from)) 一样迭代 from 中包含的文件,并且对于每个目录条目,递归调用 copy(x.path(), to/x.path().filename(), options | in-recursive-copy),其中 in-recursive-copy 是一个特殊位,当在 options 中设置时,没有其他效果。(设置此位的唯一目的是防止在 optionscopy_options::none 时递归复制子目录。)
  • 否则,不执行任何操作。

目录

[编辑] 参数

from - 源文件、目录或符号链接的路径
to - 目标文件、目录或符号链接的路径
ec - 非抛出重载中的错误报告输出参数

[编辑] 返回值

(无)

[编辑] 异常

任何未标记为 noexcept 的重载都可能在内存分配失败时抛出 std::bad_alloc

1,3) 在底层 OS API 错误时抛出 std::filesystem::filesystem_error,使用 from 作为第一个路径参数,to 作为第二个路径参数,以及 OS 错误代码作为错误代码参数构造。
2,4) 如果 OS API 调用失败,则将 std::error_code& 参数设置为 OS API 错误代码,如果没有错误发生,则执行 ec.clear()

[编辑] 注解

复制目录时的默认行为是非递归复制:文件会被复制,但子目录不会

// Given
// /dir1 contains /dir1/file1, /dir1/file2, /dir1/dir2
// and /dir1/dir2 contains /dir1/dir2/file3
// After
std::filesystem::copy("/dir1", "/dir3");
// /dir3 is created (with the attributes of /dir1)
// /dir1/file1 is copied to /dir3/file1
// /dir1/file2 is copied to /dir3/file2

而使用 copy_options::recursive 时,子目录及其内容也会被递归复制。

// ...but after
std::filesystem::copy("/dir1", "/dir3", std::filesystem::copy_options::recursive);
// /dir3 is created (with the attributes of /dir1)
// /dir1/file1 is copied to /dir3/file1
// /dir1/file2 is copied to /dir3/file2
// /dir3/dir2 is created (with the attributes of /dir1/dir2)
// /dir1/dir2/file3 is copied to /dir3/dir2/file3

[编辑] 示例

#include <cstdlib>
#include <filesystem>
#include <fstream>
#include <iostream>
namespace fs = std::filesystem;
 
int main()
{
    fs::create_directories("sandbox/dir/subdir");
    std::ofstream("sandbox/file1.txt").put('a');
    fs::copy("sandbox/file1.txt", "sandbox/file2.txt"); // copy file
    fs::copy("sandbox/dir", "sandbox/dir2"); // copy directory (non-recursive)
    const auto copyOptions = fs::copy_options::update_existing
                           | fs::copy_options::recursive
                           | fs::copy_options::directories_only
                           ;
    fs::copy("sandbox", "sandbox_copy", copyOptions); 
    static_cast<void>(std::system("tree"));
    fs::remove_all("sandbox");
    fs::remove_all("sandbox_copy");
}

可能的输出

.
├── sandbox
│   ├── dir
│   │   └── subdir
│   ├── dir2
│   ├── file1.txt
│   └── file2.txt
└── sandbox_copy
    ├── dir
    │   └── subdir
    └── dir2
 
8 directories, 2 files

[编辑] 缺陷报告

以下行为变更缺陷报告被追溯应用于先前发布的 C++ 标准。

DR 应用于 已发布行为 正确行为
LWG 3013 C++17 error_code 重载标记为 noexcept 但可以分配内存 noexcept 已移除
LWG 2682 C++17 尝试为目录创建符号链接成功但不执行任何操作 报告错误

[编辑] 参见

指定复制操作的语义
(枚举) [编辑]
复制符号链接
(函数) [编辑]
(C++17)
复制文件内容
(函数) [编辑]