- filesystem[meta header]
- std::filesystem[meta namespace]
- function[meta id-type]
- cpp17[meta cpp]
namespace std::filesystem {
void copy(const path& from, const path& to); // (1)
void copy(const path& from, const path& to, std::error_code& ec); // (2)
void copy(const path& from, const path& to, copy_options options); // (3)
void copy(const path& from, const path& to, copy_options options,
std::error_code& ec); // (4)
}
- path[link path.md]
- copy_options[link copy_options.md]
ファイル・ディレクトリ・シンボリックリンクをコピーする。
options
は、各グループのオプションが最大ひとつまで設定されていること
- (1) :
return copy(from, to,
copy_options::none
);
- (2) :
return copy(from, to,
copy_options::none
, ec);
- (3), (4) :
-
まず、コピー元のファイル状態
f
とコピー先のファイル状態t
を、以下のように取得する:file_status f; file_status t; if ((options & copy_options::create_symlinks) != copy_options::none || (options & copy_options::skip_symlinks) != copy_options::none) { f = symlink_status(from); t = symlink_status(to); } else if ((options & copy_options::copy_symlinks) != copy_options::none) { f = symlink_status(from); t = status(to); } else { f = status(from); t = status(to); }
- file_status[link file_status.md]
- copy_options[link copy_options.md]
- symlink_status[link symlink_status.md]
- status[link status.md]
-
以下のいずれかの場合、エラーを報告する。(3)の場合は例外、(4)の場合は
ec
にエラー情報を設定することでエラー報告とする:!
exists
(f)
equivalent
(from, to)
is_other
(f) ||
is_other
(t)
is_directory
(f) &&
is_regular_file
(t)
- また、それ以外に、ファイルコピー、シンボリックリンクのコピー、ディレクトリ作成などにおいてエラーが報告される可能性がある
-
コピー元がシンボリックリンクである場合、
(options & copy_options::skip_symlinks) != copy_options::none
であれば、なにもしないで終了する!exists(t) && (options & copy_options::copy_symlinks) != copy_options::none
であれば、copy_symlink
(from, to)
を実行する- いずれの条件にも合致しない場合は、エラーを報告する
-
コピー元が通常ファイルである場合、
(options & copy_options::directories_only) != copy_options::none
であれば、なにもしないで終了する(options & copy_options::create_symlinks) != copy_options::none
であれば、コピー元ファイルのシンボリックリンクを、コピー先に作成する(options & copy_options::create_hard_links) != copy_options::none
であれば、コピー元ファイルのハードリンクを、コピー先に作成する- コピー先がディレクトリである場合、
copy_file
(from, to/
from.filename()
, options)
を実行する - いずれの条件にも合致しない場合は、
copy_file
(from, to, options)
を実行する
-
コピー元がディレクトリであり、
(options & copy_options::create_symlinks) != copy_options::none
である場合、make_error_code
(
errc::is_a_directory
)
と等値なerror_code
オブジェクトをエラーとして報告する -
コピー元がディレクトリであり、
((options & copy_options::recursive) != copy_options::none || options == copy_options::none)
である場合、- コピー先にディレクトリが存在しない場合は、
create_directory
(to, from)
を実行する - その後、コピー元ディレクトリの全ての要素を、以下のようにコピーする (
in-recursive-copy
は、copy_options
には含まれないビットマスク要素):
for (const directory_entry& x : directory_iterator(from)) copy(x.path(), to/x.path().filename(), options | copy_options::in-recursive-copy)
- directory_entry[link directory_entry.md]
- directory_iterator[link directory_iterator.md]
- x.path()[link directory_entry/path.md]
- filename()[link path/filename.md]
- copy_options[link copy_options.md]
- in-recursive-copy[italic]
- コピー先にディレクトリが存在しない場合は、
-
いずれでもない場合、
- (3) であれば、なにもしない
- (4) であれば
ec.clear()
を呼び出し、エラー情報をクリアする
-
- (1), (3) : ファイルシステムがエラーを報告する場合がある。エラーが発生した場合は、
std::filesystem::filesystem_error
例外を送出する - (2), (4) : OSがファイルコピーの直接のAPIを定義していない場合、この関数の実装として動的なバッファを確保する可能性がある。その際、メモリ確保で例外が発生する可能性がある
#include <cassert>
#include <filesystem>
#include <fstream>
namespace fs = std::filesystem;
int main()
{
// 単純なファイルのコピー。
// コピー先にはファイルが存在していない
// (コピー先にファイルが存在していたらエラー)
{
std::ofstream{"regular1.txt"};
// ファイル"regular1.txt"を、"copy1.txt"にコピーする
fs::copy("regular1.txt", "copy1.txt");
assert(fs::exists("regular1.txt"));
assert(fs::exists("copy1.txt"));
}
// ファイルのコピー。
// コピー先にすでにファイルがある場合は、上書きする
{
std::ofstream{"regular2.txt"};
// ファイル"regular2.txt"を、"copy2.txt"にコピーする
fs::copy("regular2.txt", "copy2.txt", fs::copy_options::overwrite_existing);
assert(fs::exists("regular2.txt"));
assert(fs::exists("copy2.txt"));
}
// ファイルのコピーを、シンボリックリンクの作成として行う
{
std::ofstream{"regular3.txt"};
// ファイル"regular3.txt"へのシンボリックリンクとして、"copy3.txt"を作成する
fs::copy("regular3.txt", "copy3.txt", fs::copy_options::create_symlinks);
assert(fs::exists("regular3.txt"));
assert(fs::exists("copy3.txt"));
assert(fs::is_symlink("copy3.txt"));
}
// シンボリックリンクファイルのコピー
{
fs::create_symlink("regular3.txt", "regular4.symlink");
// シンボリックリンクファイル"regular4.symlink"を、"copy4.symlink"にコピーする
fs::copy("regular4.symlink", "copy4.symlink");
assert(fs::exists("regular4.symlink"));
assert(fs::exists("copy4.symlink"));
}
// ディレクトリのコピー
{
fs::create_directory("dir");
fs::create_directory("dir/sub_dir");
std::ofstream{"dir/a.txt"};
std::ofstream{"dir/sub_dir/b.txt"};
fs::copy("dir", "copy_dir", fs::copy_options::recursive);
assert(fs::exists("copy_dir"));
assert(fs::exists("copy_dir/sub_dir"));
assert(fs::exists("copy_dir/a.txt"));
assert(fs::exists("copy_dir/sub_dir/b.txt"));
}
}
- fs::copy[color ff0000]
- fs::exists[link exists.md]
- fs::copy_options[link copy_options.md]
- fs::is_symlink[link is_symlink.md]
- fs::create_symlink[link create_symlink.md]
- fs::create_directory[link create_directory.md]
- C++17
- Clang: 7.0 [mark verified]
- GCC: 8.1 [mark verified]
- Visual C++:
- LWG Issue 3015.
copy_options::unspecified
underspecified - LWG Issue 2682.
filesystem::copy()
won't create a symlink to a directory- C++17策定同時の仕様では、
copy("/", "root", copy_options::create_symlinks);
のような状況 (コピー元がディレクトリで、create_symlinks
オプション付き) でコピー先ディレクトリにシンボリックリンクが作られない問題があった。GNUのcp -s
コマンドでは「ディレクトリ"/"
の処理は省略された」と表示されてエラー終了する。この問題に対する仕様変更ではその動作に合わせて、コピー元がディレクトリでcreate_symlinks
オプションが指定された場合、エラーを報告するようになった - この問題は2016年4月に報告された。仕様としてはC++20に含まれるが、過去に遡ってC++17のコンパイラでもこの仕様に対応している可能性がある
- C++17策定同時の仕様では、
- LWG Issue 3013.
(recursive_)directory_iterator
construction and traversal should not benoexcept