全网整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:400-708-3566

c++怎么使用std::filesystem遍历文件夹_c++ 递归查找文件与权限修改【技巧】

应使用 try/catch 包裹迭代器初始化和递增操作,配合 directory_options::skip_permission_denied 和手动 while 循环遍历,禁用符号链接跟踪以避免崩溃;查找文件时优先用 is_regular_file() 和 extension() 判断,权限修改前需捕获 filesystem_error。

std::filesystem::recursive_directory_iterator 怎么用才不崩溃

直接用 std::filesystem::recursive_directory_iterator 遍历目录时,最常见崩溃原因是底层路径不可访问(比如权限不足、符号链接循环、挂载点失效),而默认构造器不捕获异常。必须显式处理 std::filesystem::filesystem_error

  • 永远用 try/catch 包裹迭代器初始化和递增操作,尤其在非受控环境(如用户目录、外部存储)中
  • 避免直接写
    for (auto& entry : std::filesystem::recursive_directory_iterator(path))
    —— 这会在首次 ++ 时触发访问,异常无法被 for 循环捕获
  • 改用 while 循环 + 手动递增,并在每次 ++iter 前检查 iter != std::filesystem::end(iter)
  • 传入 std::filesystem::directory_options::skip_permission_denied 可跳过无权读取的子目录,但注意:这仅影响「进入子目录」,不抑制对当前项元数据的读取失败

怎么安全地递归查找特定文件名或扩展名

不能依赖 entry.path().filename() 粗暴字符串匹配,因为大小写敏感性、编码、隐藏文件属性都可能出错;更可靠的是组合 entry.is_regular_file()entry.path().extension() 判断。

  • 扩展名比较务必用 == 而非 string::find:例如 entry.path().extension() == ".log",因为 .extension() 返回的是带点的 std::filesystem::path,不是裸字符串
  • 文件名精确匹配用 entry.path().filename() == "config.ini",注意它区分大小写(Windows 下通常不敏感,但标准行为是敏感)
  • 若需忽略大小写,先转小写再比:用 std::ranges::transform + std::tolower 处理 entry.path().filename().string(),但注意 locale 安全性,生产环境建议用 ICU 或平台 API
  • 不要在循环中反复调用 entry.status() —— 它可能触发额外系统调用;优先用 entry.is_regular_file() / entry.is_directory(),它们复用已缓存的状态

修改文件权限时 chmod 的跨平台陷阱

std::filesystem::permissions() 在 Windows 上只模拟 Unix 权限位(通过 ACL 子集),实际效果受限;Linux/macOS 下才真正映射到 chmod。直接设 owner_write 可能被静默忽略。

  • 修改前先获取当前权限:auto old_perms = std::filesystem::status(path).permissions(),再按位操作,避免覆盖执行位等意外状态
  • Windows 下想禁用写入,请用 std::filesystem::perms::owner_write | std::filesystem::perms::group_write | std::filesystem::perms::others_write,然后 & ~ 写权限位;但注意:这等价于设置只读属性,而非 Unix 式 chmod
  • 批量修改时别用递归迭代器顺手改权限——std::filesystem::permissions() 对目录生效后,新创建文件会继承父目录默认权限(umask 影响),但已有子项不受影响;要真正递归改,得自己遍历并逐个调用
  • 权限修改失败时,std::filesystem::permissions()std::filesystem::filesystem_error,错误码可能是 std::errc::operation_not_permitted(Windows 管理员权限缺失)或 std::errc::read_only_file_system(挂载为 ro)

性能关键:什么时候该关掉递归遍历的 symlink 跟踪

默认情况下 recursive_directory_iterator 会跟随符号链接进入目标目录,导致重复遍历、无限循环甚至栈溢出。除非你明确需要解析软链内容,否则必须关掉。

  • 构造时传 std::filesystem::directory_options::none:这是最安全的默认选项,完全不跟踪 symlink
  • 如果只想跳过 symlink(不报错也不进入),用 std::filesystem::directory_options::skip_permission_denied | std::filesystem::directory_options::follow_directory_symlink 是错的——follow_directory_symlink 正是你要禁用的行为
  • 检测 symlink 用 entry.is_symlink(),它不触发访问,开销极低;可据此做白名单式放行(例如只允许进入特定可信路径下的 symlink)
  • 在 SSD 上遍历百万级小文件时,关闭 symlink 跟踪可减少 15%+ 的系统调用次数;配合 std::filesystem::directory_options::skip_permission_denied,整体耗时下降明显
实际递归查找并设只读的最小可行代码片段:
void find_and_chmod_ro(const std::filesystem::path& root, const std::string& ext) {
    std::error_code ec;
    for (std::filesystem::recursive_directory_iterator iter(root, std::filesystem::directory_options::skip_permission_denied, ec), end; iter != end && !ec; ++iter) {
        if (ec) break;
        auto& entry = *iter;
        if (entry.is_regular_file() && entry.path().extension() == ext) {
            try {
                std::filesystem::permissions(entry.path(),
                    std::filesystem::perms::owner_read | std::filesystem::perms::group_read | std::filesystem::perms::others_read,
                    std::filesystem::perm_options::replace);
            } catch (const std::filesystem::filesystem_error& e) {
                // 忽略权限修改失败,继续下一个
            }
        }
    }
}
Windows 下测试时记得以管理员身份运行,否则对 Program Files 类路径的 permissions() 调用大概率失败;Linux 下则要注意 umask 是否干扰最终权限位。


# linux  # windows  # 编码  # mac  #   # unix  # c++  # macos  # win  # cos  # String  # for  # while  # try  # catch  # Filesystem  # auto  # 字符串  # 递归  # 循环  # 继承  # transform  # 遍历  # 的是  # 扩展名  # 迭代  # 而非  # 跳过  # 这是  # 也不  # 首次 


相关文章: 无锡营销型网站制作公司,无锡网选车牌流程?  如何在景安服务器上快速搭建个人网站?  建站之星3.0如何解决常见操作问题?  制作网站的软件下载免费,今日头条开宝箱老是需要下载怎么回事?  测试制作网站有哪些,测试性取向的权威测试或者网站?  如何在Golang中处理模块冲突_解决依赖版本不兼容问题  制作网站的模板软件,网站怎么建设?  胶州企业网站制作公司,青岛石头网络科技有限公司怎么样?  如何高效搭建专业期货交易平台网站?  建站之星好吗?新手能否轻松上手建站?  大型企业网站制作流程,做网站需要注册公司吗?  微信网站制作公司有哪些,民生银行办理公司开户怎么在微信网页上查询进度?  如何在自有机房高效搭建专业网站?  专业型网站制作公司有哪些,我设计专业的,谁给推荐几个设计师兼职类的网站?  Swift中switch语句区间和元组模式匹配  网站制作免费,什么网站能看正片电影?  贸易公司网站制作流程,出口贸易网站设计怎么做?  建站OpenVZ教程与优化策略:配置指南与性能提升  手机网站制作与建设方案,手机网站如何建设?  湖南网站制作公司,湖南上善若水科技有限公司做什么的?  c++怎么实现高并发下的无锁队列_c++ std::atomic原子变量与CAS操作【详解】  网站制作公司,橙子建站是合法的吗?  娃派WAP自助建站:免费模板+移动优化,快速打造专业网站  建站之星展会模版如何一键下载生成?  邀请函制作网站有哪些,有没有做年会邀请函的网站啊?在线制作,模板很多的那种?  如何快速上传自定义模板至建站之星?  如何正确下载安装西数主机建站助手?  c# Task.Yield 的作用是什么 它和Task.Delay(1)有区别吗  南京网站制作费用,南京远驱官方网站?  如何设计高效校园网站?  北京企业网站设计制作公司,北京铁路集团官方网站?  建站为何优先选择香港服务器?  如何通过虚拟主机快速完成网站搭建?  高防服务器租用指南:配置选择与快速部署攻略  如何配置支付宝与微信支付功能?  建站之星如何防范黑客攻击与数据泄露?  如何获取免费开源的自助建站系统源码?  成都品牌网站制作公司,成都营业执照年报网上怎么办理?  如何制作公司的网站链接,公司想做一个网站,一般需要花多少钱?  阿里云高弹*务器配置方案|支持分布式架构与多节点部署  魔方云NAT建站如何实现端口转发?  青浦网站制作公司有哪些,苹果官网发货地是哪里?  云南网站制作公司有哪些,云南最好的招聘网站是哪个?  小自动建站系统:AI智能生成+拖拽模板,多端适配一键搭建  山东云建站价格为何差异显著?  网站制作公司排行榜,抖音怎样做个人官方网站  Swift中循环语句中的转移语句 break 和 continue  如何自定义建站之星模板颜色并下载新样式?  手机网站制作平台,手机靓号代理商怎么制作属于自己的手机靓号网站?  C++时间戳转换成日期时间的步骤和示例代码 

您的项目需求

*请认真填写需求信息,我们会在24小时内与您取得联系。