C++17stladvanced
std::filesystem::copy_options
C++17 · Practical Modern · Compiler flag: -std=c++17
Explanation
A bitmask enumeration controlling the behavior of `copy()` and `copy_file()`, such as whether to overwrite existing files, skip them, or update only if the source is newer.
Real-World Scenario
Implement an incremental backup that only copies files newer than the destination.
Quick Snippet
snippet.cpp
#include <filesystem>
namespace fs = std::filesystem;
fs::copy_file("source.dat", "backup.dat",
fs::copy_options::update_existing);Full Example
copy_options.cpp
// CodeNebula - C++17 Example: std::filesystem::copy_options
// Compile: g++ -std=c++17 -Wall -Wextra -o example copy_options.cpp -lstdc++fs
// std::filesystem::copy_options is a bitmask controlling copy behavior:
// how to handle existing files, symlinks, and whether to copy recursively.
#include <iostream>
#include <filesystem>
#include <fstream>
namespace fs = std::filesystem;
int main() {
try {
fs::path base = fs::temp_directory_path() / "cn_copy_opts";
fs::create_directories(base);
fs::path src = base / "source.txt";
fs::path dst = base / "dest.txt";
{ std::ofstream(src) << "original content"; }
{ std::ofstream(dst) << "existing content"; }
// --- Default: fails if destination exists ---
std::cout << "=== copy_options::none (default) ===" << std::endl;
std::error_code ec;
fs::copy_file(src, dst, fs::copy_options::none, ec);
std::cout << "Copy with none: " << (ec ? "failed" : "succeeded")
<< " (" << ec.message() << ")" << std::endl;
// --- skip_existing: silently skip ---
std::cout << "\n=== copy_options::skip_existing ===" << std::endl;
bool result = fs::copy_file(src, dst, fs::copy_options::skip_existing);
std::cout << "Copied: " << result << " (false means skipped)" << std::endl;
// --- overwrite_existing: replace destination ---
std::cout << "\n=== copy_options::overwrite_existing ===" << std::endl;
result = fs::copy_file(src, dst, fs::copy_options::overwrite_existing);
std::cout << "Copied: " << result << std::endl;
// --- update_existing: copy only if source is newer ---
std::cout << "\n=== copy_options::update_existing ===" << std::endl;
result = fs::copy_file(src, dst, fs::copy_options::update_existing);
std::cout << "Copied: " << result << " (false if dest is same age or newer)" << std::endl;
// --- Demonstrate copy_options for directory copy ---
std::cout << "\n=== Directory copy options ===" << std::endl;
fs::path dir_src = base / "dir_src";
fs::path dir_dst = base / "dir_dst";
fs::create_directories(dir_src / "sub");
{ std::ofstream(dir_src / "a.txt") << "a"; }
{ std::ofstream(dir_src / "sub" / "b.txt") << "b"; }
// copy with recursive option
fs::copy(dir_src, dir_dst, fs::copy_options::recursive);
int count = 0;
for (const auto& e : fs::recursive_directory_iterator(dir_dst)) {
std::cout << " " << e.path().filename().string() << std::endl;
++count;
}
std::cout << "Entries copied recursively: " << count << std::endl;
// --- Show all option flags ---
std::cout << "\n=== Available copy_options flags ===" << std::endl;
std::cout << "none (existing file handling)" << std::endl;
std::cout << "skip_existing (silently skip)" << std::endl;
std::cout << "overwrite_existing (replace target)" << std::endl;
std::cout << "update_existing (replace if newer)" << std::endl;
std::cout << "recursive (copy directories recursively)" << std::endl;
std::cout << "copy_symlinks (copy symlinks as symlinks)" << std::endl;
std::cout << "skip_symlinks (ignore symlinks)" << std::endl;
std::cout << "directories_only (copy directory structure only)" << std::endl;
std::cout << "create_symlinks (create symlinks instead of copies)" << std::endl;
std::cout << "create_hard_links (create hard links instead)" << std::endl;
// Cleanup
fs::remove_all(base);
} catch (const fs::filesystem_error& e) {
std::cerr << "Filesystem error: " << e.what() << std::endl;
}
return 0;
}
/*
Expected output:
=== copy_options::none (default) ===
Copy with none: failed (File exists)
=== copy_options::skip_existing ===
Copied: 0 (false means skipped)
=== copy_options::overwrite_existing ===
Copied: 1
=== copy_options::update_existing ===
Copied: 0 (false if dest is same age or newer)
=== Directory copy options ===
a.txt
sub
b.txt
Entries copied recursively: 3
=== Available copy_options flags ===
none (existing file handling)
skip_existing (silently skip)
overwrite_existing (replace target)
update_existing (replace if newer)
recursive (copy directories recursively)
copy_symlinks (copy symlinks as symlinks)
skip_symlinks (ignore symlinks)
directories_only (copy directory structure only)
create_symlinks (create symlinks instead of copies)
create_hard_links (create hard links instead)
*/
Run command
g++ -std=c++17 -Wall -Wextra -o example copy_options.cpp -lstdc++fs