Namespaces
Variants

std::filesystem:: copy

From cppreference.net
定义于头文件 <filesystem>
void copy ( const std:: filesystem :: path & from,
const std:: filesystem :: path & to ) ;
(1) (C++17 起)
(2) (C++17 起)
(3) (C++17 起)
(4) (C++17 起)

复制文件和目录,提供多种选项。

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

行为如下:

  • 首先,在进行任何其他操作之前,通过不超过一次调用获取 from 的类型和权限
  • 若有必要,通过不超过一次调用获取 to 的状态
  • 如果 from to 具有实现定义的 文件类型 ,则此函数的效果由实现定义。
  • 如果 from 不存在,则报告错误。
  • 如果通过 std::filesystem::equivalent 确定 from to 是同一文件,则报告错误。
  • 如果通过 std::filesystem::is_other 确定 from to 不是常规文件、目录或符号链接,则报告错误。
  • 如果 from 是目录,但 to 是常规文件,则报告错误。
  • 如果 from 是符号链接,则
  • copy_options::skip_symlink 存在于 options 中,则不执行任何操作。
  • 否则,若 to 不存在且 copy_options::copy_symlinks 存在于 options 中,则行为如同执行 copy_symlink ( from, to )
  • 否则,报告错误。
  • 否则,如果 from 是常规文件,则
  • copy_options::directories_only 存在于 options 中,则不执行任何操作。
  • 否则,若 copy_options::create_symlinks 存在于 options 中,则创建指向 to 的符号链接。注意:除非 to 位于当前目录下,否则 from 必须是绝对路径。
  • 否则,若 copy_options::create_hard_links 存在于 options 中,则创建指向 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 是已存在还是刚被创建,都会遍历 from 中包含的文件,如同通过 for ( const std:: filesystem :: directory_entry & x : std:: filesystem :: directory_iterator ( from ) ) 进行迭代,并对每个目录条目递归调用 copy ( x. path ( ) , to / x. path ( ) . filename ( ) , options | in - recursive - copy ) ,其中 in-recursive-copy 是一个特殊标志位,当在 options 中设置时不会产生其他效果。(设置此位的唯一目的是防止在 options copy_options::none 时递归复制子目录。)
  • 否则不执行任何操作。

目录

参数

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

返回值

(无)

异常

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

1,3) 当底层操作系统API出错时抛出 std::filesystem::filesystem_error ,该异常以 from 作为第一个路径参数, to 作为第二个路径参数,并将操作系统错误代码作为错误码参数构造。
2,4) 若操作系统 API 调用失败,将 std:: error_code & 参数设置为操作系统 API 错误码;若未发生错误,则执行 ec. clear ( )

注释

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

// 给定
// /dir1 包含 /dir1/file1, /dir1/file2, /dir1/dir2
// 且 /dir1/dir2 包含 /dir1/dir2/file3
// 执行后
std::filesystem::copy("/dir1", "/dir3");
// /dir3 被创建(具有 /dir1 的属性)
// /dir1/file1 被复制到 /dir3/file1
// /dir1/file2 被复制到 /dir3/file2

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

// ...但在执行后
std::filesystem::copy("/dir1", "/dir3", std::filesystem::copy_options::recursive);
// /dir3 被创建(具有 /dir1 的属性)
// /dir1/file1 被复制到 /dir3/file1
// /dir1/file2 被复制到 /dir3/file2
// /dir3/dir2 被创建(具有 /dir1/dir2 的属性)
// /dir1/dir2/file3 被复制到 /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"); // 复制文件
    fs::copy("sandbox/dir", "sandbox/dir2"); // 复制目录(非递归)
    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++标准。

缺陷报告 适用范围 发布时的行为 正确行为
LWG 3013 C++17 error_code 重载标记为 noexcept 但可能分配内存 移除 noexcept
LWG 2682 C++17 尝试为目录创建符号链接成功但未执行任何操作 报告错误

参见

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