名稱空間
變體
操作

std::filesystem::copy

來自 cppreference.com
 
 
 
定義於標頭檔案 <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) 預設行為,等同於使用 copy_options::none 作為 options(3,4)
3,4) 使用 options 指示的複製選項,將檔案或目錄 from 複製到檔案或目錄 to。如果在 options 中存在任何 copy_options 選項組中超過一個選項(即使在 copy_file 組中),則行為未定義。

行為如下:

  • 首先,在執行任何其他操作之前,透過至多一次呼叫來獲取 from 的型別和許可權:
  • 如有必要,透過至多一次呼叫來獲取 to 的狀態:
  • 如果 fromto 具有實現定義的檔案型別,則此函式的效果是實現定義的。
  • 如果 from 不存在,則報告錯誤。
  • 如果 std::filesystem::equivalent 確定 fromto 是相同檔案,則報告錯誤。
  • 如果 std::filesystem::is_other 確定 fromto 不是常規檔案、目錄或符號連結,則報告錯誤。
  • 如果 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 的符號連結。注意:除非 to 在當前目錄中,否則 from 必須是絕對路徑。
  • 否則,如果 options 中存在 copy_options::create_hard_links,則建立指向 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 - 非丟擲過載中用於錯誤報告的出參

[編輯] 返回值

(無)

[編輯] 異常

任何未標記為 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++ 標準。

缺陷報告 應用於 釋出時的行為 正確的行為
LWG 3013 C++17 error_code 過載被標記為 noexcept 但可以分配記憶體 noexcept 已移除
LWG 2682 C++17 嘗試為目錄建立符號連結成功但什麼也沒做 報告錯誤

[編輯] 另請參閱

指定複製操作的語義
(列舉) [編輯]
複製一個符號連結
(函式) [編輯]
(C++17)
複製檔案內容
(函式) [編輯]