You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

原因分析

  1. 目录执行权限缺失:/dir/tmp/权限为0666(drw-rw-rw-),目录的**执行权限(x位)**是进入目录、访问子内容的必要条件——没有x权限,即使有读权限也无法遍历目录内的内容,更无法进入子目录data1。
  2. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 10:57:24