std::filesystem Quick Reference
C++17 std::filesystem cheatsheet — path operations, directory traversal, file queries, copy/rename/remove, permissions, and common patterns.
Path Construction
cpp
#include <filesystem>
namespace fs = std::filesystem;
fs::path p1 = "/usr/local/bin";
fs::path p2 = "data/config.json";
fs::path p3 = p1 / "clang"; // /usr/local/bin/clang
fs::path p4 = p2.parent_path(); // data
fs::path p5 = p2.filename(); // config.json
fs::path p6 = p2.stem(); // config
fs::path p7 = p2.extension(); // .json
fs::path p8 = p2.replace_extension(".yaml");
// Absolute / canonical
fs::path abs = fs::absolute(p2); // prepend cwd
fs::path can = fs::canonical("/usr/../usr/local"); // /usr/local (resolves ..)
fs::path rel = fs::relative("/usr/local", "/usr"); // local
// String conversion
std::string s = p1.string(); // native string
std::u8string u = p1.u8string(); // UTF-8
p1.generic_string(); // forward slashes on all platformsFile and Directory Queries
cpp
fs::path p = "data/file.txt";
fs::exists(p) // true/false
fs::is_regular_file(p) // true if plain file
fs::is_directory(p) // true if directory
fs::is_symlink(p) // true if symlink
fs::is_empty(p) // true if empty file or empty dir
fs::file_size(p) // size in bytes (regular file only)
fs::last_write_time(p) // fs::file_time_type
// Status
fs::file_status s = fs::status(p);
s.type() // file_type enum
s.permissions() // perms bitmaskDirectory Traversal
cpp
// Non-recursive
for (const auto& entry : fs::directory_iterator("src")) {
std::println("{} ({})", entry.path().filename().string(),
entry.is_regular_file() ? entry.file_size() : 0);
}
// Recursive
for (const auto& entry : fs::recursive_directory_iterator(".")) {
if (entry.path().extension() == ".cpp")
std::println("{}", entry.path().string());
}
// With options: skip permission denied
fs::recursive_directory_iterator it{
".", fs::directory_options::skip_permission_denied};
for (const auto& entry : it) { /* ... */ }
// Collect all .hpp files
std::vector<fs::path> headers;
for (const auto& e : fs::recursive_directory_iterator("include"))
if (e.extension() == ".hpp")
headers.push_back(e.path());Create, Copy, Move, Remove
cpp
// Create
fs::create_directory("output"); // error if parent missing
fs::create_directories("a/b/c"); // creates full path
fs::create_symlink("target", "link");
// Copy
fs::copy_file("src.txt", "dst.txt"); // error if dst exists
fs::copy_file("src.txt", "dst.txt",
fs::copy_options::overwrite_existing); // overwrite ok
fs::copy("src_dir", "dst_dir",
fs::copy_options::recursive); // copy directory tree
// Move / Rename
fs::rename("old.txt", "new.txt"); // atomic on POSIX if same filesystem
// Remove
fs::remove("file.txt"); // single file or empty dir
fs::remove_all("directory"); // recursive delete (like rm -rf)Permissions
cpp
using perms = fs::perms;
fs::permissions("file.txt", perms::owner_read | perms::owner_write);
// Add execute permission
fs::permissions("script.sh",
perms::owner_exec | perms::group_exec | perms::others_exec,
fs::perm_options::add);
// Remove write permission
fs::permissions("readonly.txt", perms::owner_write,
fs::perm_options::remove);
// Check
auto p = fs::status("file.txt").permissions();
bool owner_can_read = (p & perms::owner_read) != perms::none;Temp Files and Directories
cpp
fs::path tmp = fs::temp_directory_path(); // /tmp on Linux, %TEMP% on Windows
// tmp: /tmp
// Create unique temp file (C++ doesn't have a portable mkstemp, use OS API)
// On POSIX:
char tmpl[] = "/tmp/myapp-XXXXXX";
int fd = mkstemp(tmpl);
fs::path tmpfile{tmpl}; // now you have the path
// Temp directory: create and delete automatically
struct TempDir {
fs::path path;
TempDir() : path{fs::temp_directory_path() / fs::path{std::to_string(std::rand())}} {
fs::create_directory(path);
}
~TempDir() { fs::remove_all(path); }
};Error Handling
cpp
// Throwing overloads (default)
try {
fs::copy_file("missing.txt", "dst.txt");
} catch (const fs::filesystem_error& e) {
std::println("error: {} ({})", e.what(), e.path1().string());
}
// Non-throwing overloads — pass std::error_code
std::error_code ec;
fs::copy_file("missing.txt", "dst.txt", ec);
if (ec) std::println("failed: {}", ec.message());
// All functions have both overloads:
auto size = fs::file_size("file.txt", ec);
if (ec) { /* handle */ }Common Patterns
cpp
// Find the project root (walk up to find CMakeLists.txt)
fs::path find_root(fs::path start) {
for (auto p = fs::canonical(start); p != p.root_path(); p = p.parent_path())
if (fs::exists(p / "CMakeLists.txt")) return p;
throw std::runtime_error("project root not found");
}
// Ensure directory exists
void ensure_dir(const fs::path& p) {
if (!fs::exists(p)) fs::create_directories(p);
}
// Atomic file write (write to temp, then rename)
void atomic_write(const fs::path& target, std::string_view content) {
auto tmp = target;
tmp += ".tmp";
{ std::ofstream f{tmp}; f << content; }
fs::rename(tmp, target); // atomic on POSIX
}