C++17stladvanced
std::filesystem::rename
C++17 · Practical Modern · Compiler flag: -std=c++17
Explanation
Atomically renames or moves a file or directory within the same filesystem. If the destination exists and is a file, it is replaced; if it is a non-empty directory, an error is reported.
Real-World Scenario
Atomically swap a newly written configuration file into place to avoid partial reads.
Quick Snippet
snippet.cpp
#include <filesystem>
namespace fs = std::filesystem;
// Write to a temp file, then atomically rename
fs::rename("config.tmp", "config.json");Full Example
rename.cpp
// CodeNebula - C++17 Example: std::filesystem::rename
// Compile: g++ -std=c++17 -Wall -Wextra -o example rename.cpp -lstdc++fs
// std::filesystem::rename moves or renames a file or directory. If the
// destination exists: for files it replaces; for directories behavior is OS-defined.
#include <iostream>
#include <filesystem>
#include <fstream>
namespace fs = std::filesystem;
void list_dir(const fs::path& dir) {
for (const auto& entry : fs::directory_iterator(dir)) {
std::cout << " " << entry.path().filename().string() << std::endl;
}
}
int main() {
try {
fs::path base = fs::temp_directory_path() / "cn_rename_test";
fs::create_directories(base);
// --- Rename a file ---
std::cout << "=== Rename a file ===" << std::endl;
fs::path old_file = base / "old_name.txt";
fs::path new_file = base / "new_name.txt";
{ std::ofstream(old_file) << "rename test content"; }
std::cout << "Before:" << std::endl;
list_dir(base);
fs::rename(old_file, new_file);
std::cout << "After rename:" << std::endl;
list_dir(base);
std::cout << "Old exists: " << fs::exists(old_file) << std::endl;
std::cout << "New exists: " << fs::exists(new_file) << std::endl;
// --- Rename (move) to a subdirectory ---
std::cout << "\n=== Move file to subdirectory ===" << std::endl;
fs::path subdir = base / "dest";
fs::create_directory(subdir);
fs::path moved = subdir / "moved.txt";
fs::rename(new_file, moved);
std::cout << "File moved to: " << moved.filename() << std::endl;
std::cout << "Exists in dest: " << fs::exists(moved) << std::endl;
// --- Rename a directory ---
std::cout << "\n=== Rename a directory ===" << std::endl;
fs::path old_dir = base / "old_dir";
fs::path new_dir = base / "new_dir";
fs::create_directory(old_dir);
{ std::ofstream(old_dir / "inside.txt") << "inside"; }
fs::rename(old_dir, new_dir);
std::cout << "old_dir exists: " << fs::exists(old_dir) << std::endl;
std::cout << "new_dir exists: " << fs::exists(new_dir) << std::endl;
std::cout << "Contents of new_dir:" << std::endl;
list_dir(new_dir);
// --- Rename replaces existing file ---
std::cout << "\n=== Replace existing file ===" << std::endl;
fs::path a = base / "a.txt";
fs::path b = base / "b.txt";
{ std::ofstream(a) << "content A"; }
{ std::ofstream(b) << "content B"; }
fs::rename(a, b); // b is replaced with a's content
std::cout << "a exists: " << fs::exists(a) << std::endl;
std::cout << "b exists: " << fs::exists(b) << std::endl;
std::ifstream ifs(b);
std::string content;
std::getline(ifs, content);
std::cout << "b content: \"" << content << "\"" << std::endl;
// --- Error code variant ---
std::cout << "\n=== Error handling ===" << std::endl;
std::error_code ec;
fs::rename(base / "nonexistent", base / "target", ec);
std::cout << "Rename nonexistent: " << ec.message() << 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:
=== Rename a file ===
Before:
old_name.txt
After rename:
new_name.txt
Old exists: 0
New exists: 1
=== Move file to subdirectory ===
File moved to: moved.txt
Exists in dest: 1
=== Rename a directory ===
old_dir exists: 0
new_dir exists: 1
Contents of new_dir:
inside.txt
=== Replace existing file ===
a exists: 0
b exists: 1
b content: "content A"
=== Error handling ===
Rename nonexistent: No such file or directory
*/
Run command
g++ -std=c++17 -Wall -Wextra -o example rename.cpp -lstdc++fs