std::filesystem递归目录迭代器权限拒绝:0777目录无法遍历
问题分析与解决:std::filesystem递归遍历权限报错
问题核心
使用C++ std::filesystem库递归遍历目录时触发权限错误:
filesystem error: cannot increment recursive directory iterator: Permission denied
程序可进入/dir/和/dir/tmp/,但无法访问dir/tmp/data1,所有目录UID/GID一致,权限显示为0777/0666。
相关信息
代码片段
auto const dir = std::filesystem::path(...); std::error_code ec (0, std::generic_category()); try { for (auto const& inner_entry : std::filesystem::recursive_directory_iterator(dir, std::filesystem::directory_options::follow_directory_symlink, ec)) { std::cout << "Trying to set " << inner_entry.path().c_str() << "to 0666\n"; try { // Code setting permissions on file to 0666 } catch (std::exception const& e) { std::cout << "Cannot set " << inner_entry.path().c_str() << "to 0666\n"; } } } catch (std::exception const& e) { std::cout << "Cannot for loop with: " << e.what() << ", " << ec.message(); }
目录结构
dir/tmp/data1/ dir1/ dir2/ file1 file2
stat输出
File: /dir Size: 1024 Blocks: 2 IO Block: 1024 directory Device: 706h/1798d Inode: 1897 Links: 3 Access: (0777/drwxrwxrwx) Uid: ( default) Gid: ( default) File: /dir/tmp/ Size: 1024 Blocks: 2 IO Block: 1024 directory Device: 706h/1798d Inode: 1899 Links: 3 Access: (0666/drw-rw-rw-) Uid: ( default) Gid: ( default) File: /dir/tmp/data1 Size: 1024 Blocks: 2 IO Block: 1024 directory Device: 706h/1798d Inode: 1900 Links: 6 Access: (0777/drwxrwxrwx) Uid: ( default) Gid: ( default)
程序输出
Trying to set dir/ to 0666 Trying to set dir/tmp/ to 0666 Cannot for loop with: filesystem error: cannot increment recursive directory iterator: Permission denied, Success
原因分析
- 目录执行权限缺失:
/dir/tmp/权限为0666(drw-rw-rw-),目录的**执行权限(x位)**是进入目录、访问子内容的必要条件——没有x权限,即使有读权限也无法遍历目录内的内容,更无法进入子目录data1。 - error_code使用错误:范围for循环中,迭代器递增操作出错时会直接抛出异常,不会更新你传入的
ec变量,导致捕获异常时ec仍为初始的0值,因此显示"Success"。
修复方案
1. 修复目录权限
先给/dir/tmp/添加执行权限:
chmod +x /dir/tmp/
目录必须拥有x权限,进程才能进入并访问其内部的文件或子目录。
2. 修正代码的错误处理逻辑
改用非抛出式迭代器操作,遇到错误时跳过异常目录,继续遍历:
auto const dir = std::filesystem::path(...); std::error_code ec; // 构造迭代器时先检查错误 std::filesystem::recursive_directory_iterator it(dir, std::filesystem::directory_options::follow_directory_symlink, ec); if (ec) { std::cout << "Failed to create iterator: " << ec.message() << "\n"; return; } for (; it != std::filesystem::recursive_directory_iterator(); it.increment(ec)) { if (ec) { std::cout << "Skip error dir " << it->path() << ": " << ec.message() << "\n"; ec.clear(); continue; } auto const& inner_entry = *it; std::cout << "Trying to set " << inner_entry.path().c_str() << " to 0666\n"; try { // 明确设置权限的代码 std::filesystem::permissions( inner_entry.path(), std::filesystem::perms::owner_read | std::filesystem::perms::owner_write | std::filesystem::perms::group_read | std::filesystem::perms::group_write | std::filesystem::perms::others_read | std::filesystem::perms::others_write ); } catch (const std::exception& e) { std::cout << "Cannot set " << inner_entry.path().c_str() << " to 0666: " << e.what() << "\n"; } }
- 使用
it.increment(ec)进行非抛出式递增,捕获错误后可跳过异常目录继续遍历。 - 构造迭代器时直接检查错误,避免后续异常。
- 补全权限设置的具体代码,替换原注释部分。
内容的提问来源于stack exchange,提问作者aaa
相关产品推荐
相关产品推荐

