C++17stladvanced
std::filesystem::copy / copy_file
C++17 · Practical Modern · Compiler flag: -std=c++17
Explanation
`copy` copies files, directories, or symlinks with configurable options. `copy_file` is specifically for regular files and returns a boolean indicating success. Both respect `copy_options` for conflict resolution.
Real-World Scenario
Deploy built artifacts by copying them from a build directory to a staging area.
Quick Snippet
snippet.cpp
#include <filesystem>
namespace fs = std::filesystem;
fs::copy_file("build/app.bin", "deploy/app.bin",
fs::copy_options::overwrite_existing);
fs::copy("assets/", "deploy/assets/",
fs::copy_options::recursive);Full Example
copy_file.cpp
// CodeNebula - C++17 Example: std::filesystem::copy_file
// Compile: g++ -std=c++17 -Wall -Wextra -o example copy_file.cpp -lstdc++fs
// std::filesystem::copy_file copies a single file. It supports options to
// skip, overwrite, or update existing destinations.
#include <iostream>
#include <filesystem>
#include <fstream>
namespace fs = std::filesystem;
void show_file(const fs::path& p) {
std::ifstream ifs(p);
std::string content;
std::getline(ifs, content);
std::cout << p.filename().string() << ": \"" << content
<< "\" (" << fs::file_size(p) << " bytes)" << std::endl;
}
int main() {
try {
fs::path base = fs::temp_directory_path() / "cn_copy_file";
fs::create_directory(base);
fs::path src = base / "source.txt";
fs::path dst = base / "copy.txt";
{ std::ofstream(src) << "Hello from source file!"; }
// --- Basic copy ---
std::cout << "=== Basic copy_file ===" << std::endl;
bool copied = fs::copy_file(src, dst);
std::cout << "Copied: " << copied << std::endl;
show_file(src);
show_file(dst);
// --- Copy fails if destination exists ---
std::cout << "\n=== Copy to existing (default) ===" << std::endl;
std::error_code ec;
fs::copy_file(src, dst, ec);
std::cout << "Error: " << ec.message() << std::endl;
// --- Overwrite existing ---
std::cout << "\n=== overwrite_existing ===" << std::endl;
{ std::ofstream(src) << "Updated source content"; }
copied = fs::copy_file(src, dst, fs::copy_options::overwrite_existing);
std::cout << "Overwritten: " << copied << std::endl;
show_file(dst);
// --- Skip existing ---
std::cout << "\n=== skip_existing ===" << std::endl;
{ std::ofstream(src) << "Even newer content"; }
copied = fs::copy_file(src, dst, fs::copy_options::skip_existing);
std::cout << "Copied (should be false): " << copied << std::endl;
show_file(dst); // Still has old content
// --- Copy preserves file size ---
std::cout << "\n=== Size verification ===" << std::endl;
fs::path big_src = base / "big.dat";
fs::path big_dst = base / "big_copy.dat";
{ std::ofstream ofs(big_src); for (int i = 0; i < 100; ++i) ofs << "data line\n"; }
fs::copy_file(big_src, big_dst);
std::cout << "Source size: " << fs::file_size(big_src) << std::endl;
std::cout << "Copy size: " << fs::file_size(big_dst) << std::endl;
std::cout << "Sizes match: " << (fs::file_size(big_src) == fs::file_size(big_dst)) << 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:
=== Basic copy_file ===
Copied: 1
source.txt: "Hello from source file!" (23 bytes)
copy.txt: "Hello from source file!" (23 bytes)
=== Copy to existing (default) ===
Error: File exists
=== overwrite_existing ===
Overwritten: 1
copy.txt: "Updated source content" (22 bytes)
=== skip_existing ===
Copied (should be false): 0
copy.txt: "Updated source content" (22 bytes)
=== Size verification ===
Source size: 1000
Copy size: 1000
Sizes match: 1
*/
Run command
g++ -std=c++17 -Wall -Wextra -o example copy_file.cpp -lstdc++fs