最直接方式是用std::filesystem::directory_iterator(单层)或recursive_directory_iterator(递归),需启用c++17、包含、处理filesystem_error异常,并注意路径存在性检查与符号链接行为。

用 std::filesystem 遍历目录最直接(C++17+)
如果你的编译器支持 C++17(如 GCC 8+、Clang 7+、MSVC 2017 Update 15.7+),std::filesystem 是首选。它跨平台、语义清晰,且不用手动处理路径分隔符或递归逻辑。
常见错误是忽略命名空间或未启用标准库文件系统支持:
-
g++编译时需加-lstdc++fs(GCC 8–10),GCC 11+ 和 Clang 通常自动链接 - MSVC 默认开启,但需确保项目设置中启用 C++17 或更高标准
- 路径字符串建议用
u8"dir_name"或R"(path\to\dir)"避免转义问题
示例:只获取当前目录下一级文件名(不含子目录)
#include <filesystem>
#include <iostream>
namespace fs = std::filesystem;
for (const auto& entry : fs::directory_iterator("data")) {
if (fs::is_regular_file(entry)) {
std::cout
<h3>需要递归遍历?用 <code>fs::recursive_directory_iterator</code>
</h3>
<p>和 <code>directory_iterator</code> 行为一致,但会进入子目录。注意它默认跳过符号链接(除非显式启用),且迭代顺序不保证稳定 —— 不要依赖“先文件后目录”或字母序。</p>
<p>容易踩的坑:</p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/gongju/2823" title="C++14"><img
src="https://img.php.cn/upload/manual/001/431/639/6ac8b33c327c4749.png" alt="C++14" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/gongju/2823" title="C++14" class="overflowclass">C++14</a>
<p class="overflowclass">C++14 对 C++11 的修正与增强版本,适合旧系统维护和较老工具链兼容。</p>
</div>
<a rel="nofollow" href="/xiazai/gongju/2823" title="C++14" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div>
<ul>
<li>没捕获异常:<code>std::filesystem::filesystem_error</code> 可能在权限不足或路径被删除时抛出,尤其在多线程/多进程环境中</li>
<li>误用 <code>entry.path()</code>:它返回完整路径;若只要文件名,必须调用 <code>.filename()</code>,否则得到的是 <code>"./sub/dir/file.txt"</code> 而非 <code>"file.txt"</code>
</li>
<li>性能敏感场景慎用递归迭代器:它内部维护栈结构,比单层遍历略重;若只需深度 1,别用它</li>
</ul>
<h3>旧编译器(C++11/14)怎么办?用 <code>dirent.h</code>(Linux/macOS)或 <code>FindFirstFile</code>(Windows)</h3>
<p>没有 <code>std::filesystem</code> 时,得写平台分支代码。别试图用 <code>system("ls")</code> 解析输出 —— 安全性差、不可靠、无法处理含空格或换行的文件名。</p>
<p>关键差异点:</p>
<ul>
<li>Linux/macOS:<code>dirent.h</code> 中 <code>readdir()</code> 返回 <code>struct dirent*</code>,<code>d_name</code> 字段是 C 风格字符串,需注意长度限制(<code>NAME_MAX</code>)</li>
<li>Windows:<code>FindFirstFile</code> 的 <code>WIN32_FIND_DATA.cFileName</code> 是宽字符(<code>wchar_t</code>),用 <code>MultiByteToWideChar</code> 或直接以 UTF-16 处理,避免 ANSI 乱码</li>
<li>两者都不递归;如需递归,得自己写栈或队列模拟,且要注意软链接循环引用风险</li>
</ul>
<h3>为什么不用 <code>glob()</code> 或 <code>scandir()</code>?</h3>
<p><code>glob()</code>(POSIX)看起来简洁,但它只支持简单通配符(<code>*</code>, <code>?</code>, <code>[...]</code>),不支持正则,且结果不包含文件类型信息 —— 你无法区分同名的文件和目录,还得额外调用 <code>stat()</code> 判断,反而增加开销。</p>
<p><code>scandir()</code> 虽然能过滤并排序,但:</p>
<ul>
<li>排序函数(<code>alphasort</code>)行为受 locale 影响,可能不符合预期</li>
<li>回调函数里不能抛异常(C ABI 约束),错误处理笨重</li>
<li>Windows 不原生支持,需第三方移植,维护成本高</li>
</ul>
<p>真正麻烦的不是“怎么列出文件”,而是“如何安全、可移植、可维护地做这件事”。<code>std::filesystem</code> 把路径解析、类型判断、异常语义都收束到标准里;如果项目卡在旧标准,优先封装一层跨平台的轻量目录遍历工具,而不是每处都写条件编译。</p></iostream></filesystem>C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










