std::filesystem::directory_iterator 不支持 *.txt 通配符,因为它仅提供路径遍历功能,不内置模式匹配逻辑;通配符需手动解析并用 std::regex 等工具在迭代中比对文件名。

为什么 std::filesystem::directory_iterator 不支持 *.txt 通配符?
因为 C++ 标准库的 std::filesystem(C++17 起)只提供路径遍历能力,不内置通配符匹配逻辑——它返回的是原始文件名,*.txt 这类模式得你自己解析和比对。
常见错误是直接把 "*.txt" 当作路径传给 std::filesystem::directory_iterator,结果抛出 std::filesystem::filesystem_error(系统找不到指定路径),或者静默跳过所有文件。
- 通配符匹配必须在迭代过程中对每个
entry.path().filename().string()手动判断 -
std::filesystem本身没有glob或fnmatch等等价函数 - Windows 和 POSIX 系统底层行为一致,但跨平台时注意大小写:NTFS 默认不区分,Linux ext4 区分
用 std::regex 实现 *.txt 安全匹配
最直接、可读性好、且能处理复杂模式(如 a?b*.log)的方式是转义通配符后构造正则表达式。注意别用原始字符串字面量直接塞 "*.txt" 到 std::regex,否则 * 会被当正则元字符导致崩溃或误匹配。
正确做法是先将 shell 风格通配符转换为等效正则:
-
*→.* -
?→. - 其它字符(如
.、[)需转义,避免被正则引擎解释
示例代码片段(仅核心逻辑):
std::string pattern_to_regex(const std::string& pattern) {
std::string regex;
for (char c : pattern) {
if (c == '*') regex += ".*";
else if (c == '?') regex += ".";
else if (std::regex_constants::syntax_character(c)) regex += "\";
regex += c;
}
return "^" + regex + "$";
}
// 使用
std::regex re(pattern_to_regex("*.txt"));
for (const auto& entry : std::filesystem::directory_iterator(".")) {
std::string name = entry.path().filename().string();
if (std::regex_match(name, re)) {
std::cout
<h3>更轻量:手写简单通配符匹配(无正则依赖)</h3>
<p>如果只匹配 <code>*.txt</code>、<code>log?.dat</code> 这类基础模式,且不想引入 <code><regex></regex></code>(某些嵌入式或旧编译器不完全支持),可用递归函数实现 O(n) 匹配,性能更好、无异常风险。</p>
<p>关键点:</p>
- 函数签名建议为
bool match_wildcard(const std::string& str, const std::string& pattern) - 遇到
*时尝试从当前位开始“吃掉”不同长度的字符,回溯判断剩余部分是否匹配 - 务必加边界检查,防止栈溢出或无限循环(比如
**.txt要合并为单个*) - 注意空字符串匹配:
"a.txt"vs"*.txt"✅,""vs"*"✅,"x"vs"*y"❌
Windows 下慎用 _findfirst/_findnext,Linux 别硬套 glob()
这些 C 风格 API 虽然原生支持通配符,但会带来严重移植问题:
-
_findfirst是 MSVC 特有,GCC/Clang 不识别;glob()在 macOS 上行为与 Linux 有细微差异(比如对~展开) - 它们返回的是 C 字符串数组或句柄,需手动管理生命周期,容易内存泄漏或
closedir忘记调用 - 路径分隔符不统一:
_findfirst("*.txt")在 Windows 可行,但在 WSL 或 Cygwin 下可能因路径语义混乱而漏匹配
除非你明确锁定单一平台且已有稳定封装,否则优先走 std::filesystem + 自定义匹配 这条标准路径。
真正麻烦的不是写匹配逻辑,而是处理路径编码(尤其是 Windows 上的 UTF-16)、符号链接循环、权限拒绝导致的迭代中断——这些都得在 try/catch 里单独应对,不能指望通配符函数帮你兜底。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











