std::filesystem::permissions() 是直接覆写权限位而非增量修改,需显式构造完整掩码或指定 perm_options::add/remove;Windows 仅支持读写映射,且符号链接需 nofollow 才操作本身。

std::filesystem::permissions() 的作用不是“修改权限”而是“设置权限位”
很多人看到函数名 permissions() 就默认它是 chmod 那种“修改”操作,实际它更接近 chmod --no-dereference 的语义:**直接覆写目标路径的权限位(mode bits),不叠加、不保留原值**。如果你想要“加读权限”或“去掉执行位”,不能直接传 perms::owner_read,否则其他位(如 group_write)会被清零。
正确设置权限的三种常见模式
必须显式构造完整的权限掩码,通常用按位或组合 perms 枚举值。常用组合有:
-
perms::owner_read | perms::owner_write | perms::group_read | perms::others_read→ 等效于0644 -
perms::owner_read | perms::owner_write | perms::owner_exec | perms::group_read | perms::group_exec | perms::others_read | perms::others_exec→ 等效于0755 -
perms::owner_read | perms::owner_write→ 等效于0600(仅所有者可读写)
注意:perms 枚举值不含 sticky bit、setuid/setgid —— 这些在 POSIX 上无法通过 std::filesystem::permissions() 设置,C++ 标准未要求支持。
调用时必须指定 perm_options 参数
如果不传 perm_options,默认是 perm_options::replace,即完全替换权限位;但你可能需要:
立即学习“C++免费学习笔记(深入)”;
-
perm_options::add:按位或新增权限(例如只加执行权) -
perm_options::remove:按位与取反后移除权限(例如只去掉 group_write) -
perm_options::replace:默认,彻底覆盖(最常用也最安全)
示例:给文件增加所有者执行权限,同时保留原有权限:
std::filesystem::permissions("script.sh",
std::filesystem::perms::owner_exec,
std::filesystem::perm_options::add);
错误写法(会清空所有其他权限):
std::filesystem::permissions("script.sh", std::filesystem::perms::owner_exec); // ❌
Windows 下的行为差异和兼容性陷阱
Windows 没有 Unix-style 的 rwx 三元组,std::filesystem::permissions() 在 Windows 上仅映射两个状态:
- 如果设置了
perms::owner_write→ 文件“可写”(readonly 属性被清除) - 否则 → 文件设为“只读”(设置 readonly 属性)
其他权限位(如 group_exec)在 Windows 上被忽略,不会报错但也不生效。跨平台代码若依赖 group/others 权限,需自行判断 OS 并跳过或 warn。
另外:对目录设置 perms::owner_exec 在 Windows 上无意义(目录始终可遍历),但不会失败;而尝试对符号链接调用 permissions() 时,std::filesystem 默认操作的是目标文件(非链接本身),除非你显式传 std::filesystem::symlink_option::nofollow —— 但该选项仅在 C++20 起部分编译器支持(GCC 13+、Clang 15+),MSVC 仍不支持。
权限变更是否生效,还取决于当前进程是否有对应访问令牌(Windows)或有效 UID/GID(Linux)。静默失败很常见,务必检查异常:
try {
std::filesystem::permissions("file.txt", std::filesystem::perms::rw__r__r__);
} catch (const std::filesystem::filesystem_error& e) {
// e.what() 可能是 "Operation not permitted" 或 "Permission denied"
}
真正麻烦的不是怎么写,而是忘记检查异常、误以为 add 是增量更新、以及在 Windows 上对 group 权限抱有幻想。











