C++ Filesystem Explained | std::filesystem (C++17) guide
이 글의 핵심
std::filesystem (C++17) is the standard way to work with paths, directories, file copy, and deletion. This guide covers path, exists, create_directory, copy, and common namespace patterns with examples.
What is filesystem?
If you want to combine paths, check existence, and create or remove directories using only the standard library, it pays to internalize how filesystem is designed. This article walks through the fs namespace alias and path objects, focusing on operations you use often in production.
Filesystem library (C++17)
#include <filesystem>
namespace fs = std::filesystem;
fs::path p = "/home/user/file.txt";
bool exists = fs::exists(p);
Basic operations
#include <filesystem>
namespace fs = std::filesystem;
// Check existence
if (fs::exists("file.txt")) {}
// Create directory
fs::create_directory("mydir");
// Delete file
fs::remove("file.txt");
// Copy
fs::copy("src.txt", "dst.txt");
Practical examples
Example 1: File information
#include <filesystem>
#include <iostream>
namespace fs = std::filesystem;
void printFileInfo(const fs::path& p) {
if (!fs::exists(p)) {
std::cout << "File not found" << std::endl;
return;
}
std::cout << "Path: " << p << std::endl;
std::cout << "Size: " << fs::file_size(p) << " bytes" << std::endl;
if (fs::is_regular_file(p)) {
std::cout << "Regular file" << std::endl;
} else if (fs::is_directory(p)) {
std::cout << "Directory" << std::endl;
}
}
Example 2: Directory iteration
void listFiles(const fs::path& dir) {
for (const auto& entry : fs::directory_iterator(dir)) {
std::cout << entry.path() << std::endl;
}
}
void listFilesRecursive(const fs::path& dir) {
for (const auto& entry : fs::recursive_directory_iterator(dir)) {
std::cout << entry.path() << std::endl;
}
}
Example 3: Copying files
void backupFiles(const fs::path& src, const fs::path& dst) {
if (!fs::exists(dst)) {
fs::create_directories(dst);
}
for (const auto& entry : fs::directory_iterator(src)) {
fs::path dstPath = dst / entry.path().filename();
if (fs::is_regular_file(entry)) {
fs::copy_file(entry.path(), dstPath,
fs::copy_options::overwrite_existing);
}
}
}
Example 4: Temporary files
#include <fstream>
void createTempFile() {
fs::path tempDir = fs::temp_directory_path();
fs::path tempFile = tempDir / "myapp_temp.txt";
std::ofstream ofs(tempFile);
ofs << "Temporary data" << std::endl;
ofs.close();
// Remove when done
fs::remove(tempFile);
}
Path manipulation
Sample C/C++-style path usage:
fs::path p = "/home/user/file.txt";
p.filename(); // "file.txt"
p.extension(); // ".txt"
p.stem(); // "file"
p.parent_path(); // "/home/user"
// Join paths
fs::path dir = "/home/user";
fs::path file = dir / "file.txt";
Common pitfalls
Pitfall 1: Exception handling
// ❌ Ignoring exceptions
fs::remove("file.txt"); // May throw if something goes wrong
// ✅ try/catch
try {
fs::remove("file.txt");
} catch (const fs::filesystem_error& e) {
std::cout << "Error: " << e.what() << std::endl;
}
// ✅ error_code overload
std::error_code ec;
fs::remove("file.txt", ec);
if (ec) {
std::cout << "Error: " << ec.message() << std::endl;
}
Pitfall 2: Path separators
// ❌ Platform-specific
fs::path p = "dir\\file.txt"; // Windows-oriented
// ✅ Portable
fs::path p = "dir" / "file.txt";
Pitfall 3: Relative paths
fs::path rel = "file.txt";
fs::path abs = fs::absolute(rel);
std::cout << "Relative: " << rel << std::endl;
std::cout << "Absolute: " << abs << std::endl;
Pitfall 4: Deleting directories
// ❌ Fails if not empty
fs::remove("dir");
// ✅ Recursive removal
fs::remove_all("dir");
Checking file types
fs::path p = "file.txt";
if (fs::is_regular_file(p)) {
std::cout << "Regular file" << std::endl;
}
if (fs::is_directory(p)) {
std::cout << "Directory" << std::endl;
}
if (fs::is_symlink(p)) {
std::cout << "Symbolic link" << std::endl;
}
FAQ
Q1: Which standard added filesystem?
A: C++17. It is the standard library for filesystem operations.
Q2: Is it portable?
A: Yes. Windows, Linux, and macOS are supported by mainstream toolchains.
Q3: How do I handle errors?
A:
try/catch- Overloads that take
std::error_code
Q4: Performance?
A: Operations use system calls. Use them where appropriate; avoid unnecessary repeated calls in hot loops.
Q5: Path separators?
A: Use the / operator on path for portability.
Q6: Where can I learn more?
A:
- C++17 — The Complete Guide
- C++ Primer
- cppreference.com — filesystem
Related posts
Posts that pair well with this topic:
- C++ Filesystem | C++17 filesystem library guide
- C++ file operations
- C++ std::filesystem::path
- C++ directory_iterator
- C++ file_status