应使用std::filesystem::directory_iterator配合手动后缀过滤:先用is_regular_file排除目录等非文件项,再检查extension()非空并转小写后匹配目标后缀。

std::filesystem::directory_iterator 怎么跳过非目标后缀文件
直接用 std::filesystem::directory_iterator 遍历目录时,它不带过滤能力——所有条目(包括子目录、隐藏文件、无后缀文件)都会吐出来。你得自己判断 entry.path().extension(),但要注意:空后缀(如 "README")返回的是空 std::filesystem::path,不能直接和字符串比较。
- 用
entry.path().extension().string() == ".txt"会崩溃或误判,因空 extension 的.string()可能返回空串或抛异常 - 正确做法是先检查
!entry.path().extension().empty(),再比对字符串 - 注意大小写:Windows 下
".TXT"和".txt"不同,Linux 区分大小写,建议统一转小写再比(用std::tolower处理每个字符)
为什么 std::filesystem::recursive_directory_iterator 不适合“只扫一级”场景
如果你只要当前目录下 .log 文件,别用 std::filesystem::recursive_directory_iterator——它默认递归进所有子目录,性能浪费且逻辑错位。C++17 没提供“带后缀过滤的递归迭代器”,所以必须手动控制层级或用非递归迭代器。
- 用
std::filesystem::directory_iterator+std::filesystem::is_regular_file(entry)排除目录项 - 想限制深度?只能自己计数:对每个
entry检查entry.path().parent_path().string().size()或拆解路径段数,但更稳的方式是不用递归迭代器 - 某些编译器(如旧版 GCC 8.3)对
recursive_directory_iterator的异常处理不完善,遇到权限错误可能直接 terminate
std::filesystem::path::extension() 的三个易错点
extension() 看似简单,实测中超过六成的后缀过滤 bug 出在这儿。
- 点号不是后缀一部分:
"archive.tar.gz"的extension()是".gz",不是".tar.gz";要拿全部扩展名得用stem().extension()套娃,但得先判空 -
"file."(结尾带点)的extension()是".",不是空;"file"(无点)才是空 - 跨平台路径分隔符不影响
extension(),但若路径含非法字符(如 Windows 下CON.txt),path()构造可能静默失败,建议加if (!exists(entry.path())) continue;
完整可跑的小片段:只列当前目录下 .cpp 和 .h 文件
没封装、没模板、不抽象,就解决“现在就要看到结果”的问题:
立即学习“C++免费学习笔记(深入)”;
#include <filesystem>
#include <iostream>
#include <string>
#include <algorithm>
<p>int main(int argc, char* argv[]) {
if (argc != 2) return 1;
const std::filesystem::path dir{argv[1]};
if (!std::filesystem::is_directory(dir)) return 1;</p><pre class='brush:php;toolbar:false;'>const std::vector<std::string> exts{".cpp", ".h", ".hpp"};
for (const auto& entry : std::filesystem::directory_iterator{dir}) {
if (!std::filesystem::is_regular_file(entry)) continue;
auto ext = entry.path().extension().string();
// 转小写便于比较
std::transform(ext.begin(), ext.end(), ext.begin(), ::tolower);
if (std::find(exts.begin(), exts.end(), ext) != exts.end()) {
std::cout << entry.path().filename().string() << "\n";
}
}}
编译时记得加 -std=c++17 和 -lstdc++fs(GCC 9+ 可省略后者);Clang 需显式链接 libc++fs。Windows 上用 MSVC 2019+ 无需额外链接。
最常漏掉的是 is_regular_file 检查——没有它,目录名、符号链接、socket 文件全会被当成“可读文件”塞进结果里。



















