std::filesystem::copy

来自cppreference.com
 
 
 
定义于头文件 <filesystem>
void copy( const std::filesystem::path& from,

           const std::filesystem::path& to );
void copy( const std::filesystem::path& from,
           const std::filesystem::path& to,

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

           const std::filesystem::path& to,
           std::filesystem::copy_options options );
void copy( const std::filesystem::path& from,
           const std::filesystem::path& to,
           std::filesystem::copy_options options,

           std::error_code& ec );
(2) (C++17 起)

复制文件与目录,带一些选项

1) 默认,等价于以 copy_options::none 为选项的 (2)
2) 复制文件或目录 from 到文件或目录 to ,使用 options 所指定的复制选项。若 options 中存在 copy_options 任一选项组中多于一个的选项(即使在无关乎 copycopy_file 组中)

行为如下:

  • 首先,在做任何事前,以对下列之一者不多于一次的调用,获得 from 的类型与权限
  • 若需要,则以对下列之一者不多于一次的调用,获取 to 的状态
  • fromto 拥有实现定义的文件类型,则此函数的效果是实现定义的。
  • from 不存在,则报告错误。
  • fromto 是如 std::filesystem::equivalent 所确定的同一文件,则报告错误
  • fromto 不是常规文件、目录或符号链接,如 std::filesystem::is_other 所确定,则报告错误
  • 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 的符号链接。注意: from 必须是绝对路径,除非 to 在当前目录中。
  • 否则,若 copy_options::create_hard_links 存在于 options ,则创建到 to 的硬链接
  • 否则,若 to 是目录,则表现如同 copy_file(from, to/from.filename(), options) (创建 from 的副本,作为 to 目录中的文件)
  • 否则,表现如同 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 设置时无其他效果的特殊位。(设置此位的独有目的是若 optionscopy_options::none 则阻止递归复制子目录)
  • 否则不做任何事。

参数

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

返回值

(无)

异常

不接受 std::error_code& 参数的重载在底层 OS API 错误时抛出 filesystem_error ,以第一 path 参数 from,第二 path 参数 to 和作为错误码参数的 OS 错误码构造。若 OS API 调用失败,则接受 std::error_code& 参数的重载设置该参数为 OS API 错误码,而若不出现错误则执行 ec.clear() 。若内存分配失败,则任何不标记为 noexcept 的重载可能抛出 std::bad_alloc

注解

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

// 给定
// /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 <iostream>
#include <fstream>
#include <filesystem>
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++ 标准。

DR 应用于 出版时的行为 正确行为
LWG 3013 C++17 error_code 重载被标记为 noexcept 但能分配内存 移除 noexcept
LWG 2682 C++17 试图为目录创建符号链接会成功但不做任何事 报告错误

参阅

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