第63回 std::filesystem
ファイル・ディレクトリ操作のクロスプラットフォームな標準 API。C 時代の stat, opendir, POSIX 依存コードから解放されます。C++17 で標準化(それ以前は Boost.Filesystem)。
1. 主要機能
| 機能 | 関数 |
| パス操作 | fs::path |
| 存在確認 | fs::exists |
| 種別判定 | is_regular_file, is_directory, is_symlink |
| ファイルサイズ | fs::file_size |
| ディレクトリ作成 | create_directory, create_directories |
| 削除 | remove, remove_all |
| コピー/名前変更 | copy, rename |
| 走査 | directory_iterator, recursive_directory_iterator |
| カレント | current_path, temp_directory_path |
2. path クラス
path基本
#include <filesystem>
namespace fs = std::filesystem;
fs::path p = "/home/user/data.txt";
p.filename(); // "data.txt"
p.extension(); // ".txt"
p.stem(); // "data"
p.parent_path(); // "/home/user"
// パスの連結(/ 演算子)
fs::path dir = "/home/user";
fs::path full = dir / "data.txt"; // OS に応じた区切り文字
// 文字列化
std::string s = full.string();
3. 存在確認・操作
典型操作filesystem
if (fs::exists(p)) {
if (fs::is_regular_file(p)) {
auto sz = fs::file_size(p);
std::cout << sz << " bytes\n";
}
}
// ディレクトリ作成
fs::create_directories("/tmp/a/b/c"); // 再帰的に作る
// コピー
fs::copy("src.txt", "dst.txt");
fs::copy("srcdir", "dstdir",
fs::copy_options::recursive);
// 削除
fs::remove("file.txt");
fs::remove_all("dir"); // 中身ごと再帰削除
4. ディレクトリ走査
直下のみdirectory_iterator
for (auto& entry : fs::directory_iterator("/path")) {
std::cout << entry.path() << "\n";
if (entry.is_regular_file()) {
std::cout << " size=" << entry.file_size();
}
}
再帰recursive_directory_iterator
for (auto& e : fs::recursive_directory_iterator("/path")) {
std::cout << e.path() << "\n";
}
// 全サブディレクトリを走査
5. 旧 API からの移行
stat() → fs::exists / fs::file_size
mkdir() → fs::create_directory
rmdir() / unlink() → fs::remove
opendir/readdir → fs::directory_iterator
getcwd() → fs::current_path()
Windows / Linux / macOS の違いを吸収してくれます。POSIX/Win32 API を直接叩く必要はほぼなくなりました。
確認クイズ
Q1. std::filesystem が標準化された C++ のバージョンは?
C++11
C++14
C++17
C++20
C++17 で標準化。それ以前は Boost.Filesystem として同等の API が提供されていました。
Q2. fs::path p = "/a/b"; p / "c" の結果は?
"/a/b c"
"/a/b/c"
コンパイルエラー
例外
/ 演算子でパスを OS ネイティブの区切り文字で連結できます。
Q3. ディレクトリを中身ごと削除する関数は?
fs::remove
fs::delete_directory
fs::remove_all
fs::rm_rf
remove は単一ファイル(または空ディレクトリ)、remove_all は再帰的に削除。
Q4. サブディレクトリも含めて全ファイルを走査するには?
directory_iterator
recursive_directory_iterator
iterate_dir
walk
recursive 版を使うとサブディレクトリも自動で展開されます。