Skip to content

Latest commit

 

History

History
198 lines (163 loc) · 9.53 KB

copy.md

File metadata and controls

198 lines (163 loc) · 9.53 KB

copy

  • 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]
    • f.type()もしくはt.type()が実装定義のファイル種別であった場合、その効果は実装定義となる

    • 以下のいずれかの場合、エラーを報告する。(3)の場合は例外、(4)の場合はecにエラー情報を設定することでエラー報告とする:

    • コピー元がシンボリックリンクである場合、

      • (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

処理系

参照