std::filesystem::create_directories 是 c++17 及以上递归创建目录的最佳方案,自动处理已存在路径与竞态条件,需链接 -lstdc++fs 并捕获权限异常;旧标准应选 boost::filesystem 或手动实现。

std::filesystem::create_directories 是最直接的解决方案
在 C++17 及以上标准中,std::filesystem::create_directories 会递归创建所有缺失的父目录,且对已存在的路径静默成功——这正是你想要的“自动检测并创建”的行为。
它比手动遍历路径、逐级调用 create_directory 安全得多,也避免了竞态条件(如 A 线程检查存在 → B 线程删除 → A 线程创建失败)。
使用前需确保:
- 编译器支持 C++17(GCC 8+、Clang 7+、MSVC 2017 15.7+)
- 链接
stdc++fs(GCC/Clang 下需显式加-lstdc++fs;MSVC 默认启用) - 包含头文件:
#include <filesystem></filesystem>
示例:
#include <filesystem>
namespace fs = std::filesystem;
int main() {
fs::path p = "/tmp/a/b/c/d";
if (fs::create_directories(p)) {
// 返回 true 表示至少创建了一个新目录
// false 表示所有路径组件均已存在(不报错)
}
return 0;
}</filesystem>
Windows 下路径分隔符和权限问题很常见
Windows 默认用反斜杠 ,但 std::filesystem::path 能自动 normalize:传入 "C:/a\b/c" 或 R"(C:c)" 都会被统一处理,无需手动替换。
但真实痛点是权限:
- 若目标驱动器根目录(如
C:)不可写,create_directories会抛出std::filesystem::filesystem_error - 错误信息类似:
Permission denied: "C: estricted" - 建议用 try/catch 捕获,并检查
.code().value()是否为EACCES(Linux/macOS)或ERROR_ACCESS_DENIED(Windows)
不要依赖 exists() 前置判断——它不能替代权限检查,且增加一次系统调用开销。
旧标准(C++11/14)下只能手撸或依赖第三方
如果你被卡在 C++11/14 环境(比如某些嵌入式或遗留构建系统),std::filesystem 不可用。此时有两条路:
- 用 POSIX API(Linux/macOS):
mkdir -p的等效逻辑需循环调用mkdir(),每次截断最后一级路径,直到ENOENT消失或遇到非路径错误 - 用 Windows API(Win32):
CreateDirectory()不递归,需配合PathCchRemoveFileSpec()或字符串分割手动拆解路径 - 更稳妥的做法是接入
boost::filesystem::create_directories(接口与标准版几乎一致,且兼容旧编译器)
注意:手写递归 mkdir 容易漏掉 EEXIST 判断(Linux 下 mkdir 已存在目录会失败,必须忽略该错误)。
create_directories 和 create_directory 的关键区别
这是最容易混淆的一点:create_directory 只创建**最后一级**,要求父目录必须已存在;而 create_directories 创建**所有缺失的中间目录**。
例如路径 /a/b/c:
- 若
/a存在但/a/b不存在,create_directory("/a/b/c")必然失败 -
create_directories("/a/b/c")会依次创建/a/b和/a/b/c - 两者都返回
bool:true 表示“本次调用创建了至少一个新目录”,false 表示“路径已完整存在”
别被函数名里的 “directory” 单数形式误导——create_directories 才是真正做多级创建的那个。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











