Windows用FindFirstFile/FindNextFile需跳过"."和".."、拼接路径、调用FindClose;Linux/macOS用opendir/readdir需stat判断类型;C++17推荐std::filesystem::directory_iterator,跨平台且安全,但需捕获filesystem_error异常。

Windows下用 FindFirstFile 和 FindNextFile 遍历目录
Windows API 提供最直接的原生方式,无需第三方库,但要注意跳过 "." 和 ".." 两个特殊目录项。返回的文件名是宽字符(WCHAR),若项目未启用 Unicode,需用 FindFirstFileA 等 ANSI 版本。
常见错误:直接把 FindFirstFile 返回的 WIN32_FIND_DATA::cFileName 当作完整路径使用——它只是文件名,不含路径前缀。
- 搜索模式必须带通配符,例如
"C:\\mydir\\*",不能只写"C:\\mydir" - 调用
FindClose是必须的,否则句柄泄漏 -
dwFileAttributes字段判断是否为目录:(data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
Linux/macOS 用 opendir/readdir 获取文件列表
POSIX 标准接口,返回的是 struct dirent*,其中 d_name 是文件名(不含路径),同样要手动过滤 "." 和 ".."。
注意 readdir 不保证顺序,也不区分文件/目录类型——需额外调用 stat 判断,否则可能把子目录当普通文件处理。
立即学习“C++免费学习笔记(深入)”;
- 必须检查
opendir返回值是否为nullptr,空路径或权限不足时会失败 -
readdir可能返回nullptr表示结束,但不表示出错;出错需查errno - 如果需要完整路径,得手动拼接:
std::string(path) + "/" + entry->d_name
C++17 的 std::filesystem::directory_iterator 更简洁可靠
跨平台首选,自动处理路径拼接、编码、隐藏文件过滤(可选),且支持范围 for 循环。但要注意:默认不递归,且某些旧编译器(如 GCC 8 以下)需手动链接 -lstdc++fs。
容易忽略的一点:directory_iterator 构造时若路径不存在或无权限,会抛出 std::filesystem::filesystem_error 异常,不捕获会导致程序终止。
- 遍历示例:
for (const auto& entry : std::filesystem::directory_iterator("path")) { ... } - 获取文件名用
entry.path().filename(),完整路径用entry.path() - 判断是否为普通文件:
entry.is_regular_file();是否为目录:entry.is_directory()
为什么不用 system("ls") 或 popen?
看似简单,实则隐患多:输出格式依赖 locale 和 shell 版本;文件名含空格、换行或非 UTF-8 字符时极易解析失败;无法获取文件属性(大小、时间等);Windows 下命令名和参数格式又不同。
更关键的是,这类方式绕过了 C++ 的类型安全与异常机制,错误只能靠字符串匹配或 exit code 判断,调试成本高。
- 除非明确只要“快速看一眼”,否则不建议在正式逻辑中使用
popen -
std::filesystem在 C++17 后已足够成熟,Windows 和主流 Linux 发行版都支持良好 - 若必须兼容 C++14 及更早版本,优先封装
FindFirstFile(Win)+opendir(POSIX)双实现
follow_symlink 控制可能陷入死循环。这些细节不显眼,但一出问题就很难定位。










