std::filesystem::create_directories比mkdir -p更可靠,因其是C++17标准定义的跨平台原子操作,自动逐级创建缺失父目录,且统一处理路径分隔符、Unicode、符号链接及错误异常,避免手写递归的边界问题。

std::filesystem::create_directories 为什么比 mkdir -p 更可靠
因为 std::filesystem::create_directories 是 C++17 标准定义的原子操作,它会逐级检查并创建缺失的父目录,且在 Windows、Linux、macOS 上行为一致。而手写递归调用 mkdir 或 CreateDirectory 容易漏掉权限、路径分隔符、已存在目录等边界情况。
常见错误现象:std::filesystem::create_directory(注意不是 create_directories)只建最后一级,父目录不存在时直接返回 false;或者用 std::filesystem::status 检查路径前没处理 std::filesystem::file_status 的 no_status 状态,导致误判路径不可写。
- 必须用
create_directories,不是create_directory - 路径字符串建议统一用正斜杠
/,std::filesystem内部会自动适配平台分隔符(Windows 下也认/) - 若路径含中文或 Unicode 字符,在 Windows 上需确保编译器启用 UTF-8 源码支持(如 MSVC 加
/utf-8),否则可能抛std::filesystem::filesystem_error
跨平台路径拼接别用字符串 +,要用 std::filesystem::path /
手动拼接 "a" + "/" + "b" 在 Windows 下生成 a/b,但某些旧版 MinGW 或 Cygwin 可能不识别;更严重的是,当某段路径含 (比如用户输入)时,"C:\tmp" + "/data" 会变成 C: mp/data,触发未定义行为。
正确做法是用 std::filesystem::path 的 / 重载:
立即学习“C++免费学习笔记(深入)”;
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
std::filesystem::path p = "a"; p /= "b"; // 等价于 p = p / "b" p /= "c.txt"; // 最终在 Windows 上是 ac.txt,Linux/macOS 是 a/b/c.txt std::filesystem::create_directories(p.parent_path());
-
p.parent_path()自动截掉最后一段(文件名或末尾斜杠),安全获取目录部分 - 避免对路径字符串做
.c_str()后传给系统 API ——std::filesystem已封装好,没必要绕路 - 如果路径来自用户输入,先用
std::filesystem::weakly_canonical归一化(解决../、重复/等问题),再创建
权限控制:Linux/macOS 默认 0755,Windows 不生效
std::filesystem::create_directories 不接受权限参数,它依赖系统默认 umask(Linux/macOS)或安全描述符(Windows)。这意味着你在 Linux 上跑出的目录可能是 0700(被 umask 掩掉),而非预期的 0755;Windows 则完全忽略权限位,新建目录继承父目录 ACL。
若需显式设权限,只能创建后补调:
auto p = std::filesystem::path{"my/nested/dir"};
std::filesystem::create_directories(p);
#ifdef __linux__
chmod(p.c_str(), 0755); // 需要 <sys/stat.h>
#endif
- 不要在 Windows 上调
chmod,会编译失败或静默忽略 - 避免用
std::filesystem::permissions改权限——它底层调的是chmod或SetFileAttributes,但对目录递归无效,且 Windows 对权限粒度控制很弱 - 真正需要细粒度权限时(如 Docker 容器内),应由部署流程统一设置,而非在运行时硬编码
错误处理不能只看 return bool,得捕获 filesystem_error
create_directories 返回 bool 表示“是否新建了至少一个目录”,但它成功也可能因权限不足、磁盘满、符号链接断裂等失败——此时会抛 std::filesystem::filesystem_error,而不是返回 false。
典型误用:
if (!std::filesystem::create_directories(p)) {
// 这里以为只是“目录已存在”,但其实可能根本没进到这行——异常已抛出
}
- 必须用
try/catch捕获std::filesystem::filesystem_error - 异常的
.code().value()可对应系统 errno(Linux/macOS)或 Win32 错误码(Windows),比如13是 Permission denied,2是 No such file or directory - 若想静默忽略“已存在”错误,可检查
e.code() == std::errc::file_exists,但注意:该错误仅在尝试创建已存在**文件**时抛出,目录已存在不会报错,create_directories直接返回false
最常被忽略的是符号链接路径——如果 p 中间某段是悬空 symlink,create_directories 在 Linux/macOS 上会失败并抛 std::errc::not_a_directory,Windows 则可能成功也可能失败,取决于 symlink 类型和权限。这种场景下,得先 std::filesystem::exists + std::filesystem::is_symlink 做预检。

















