<p>PHP 7.3+ 原生支持 glob() 的 递归通配符,但需配合 GLOB_BRACE 标志;PHP 7.2 及更早版本完全不识别 ,将其视为字面量导致匹配失败,推荐跨版本使用 RecursiveDirectoryIterator 替代。</p>

glob() 在 PHP 7.3 引入了对 ** 递归通配符的原生支持,而 PHP 7.2 及更早版本不识别它——直接写 glob('/path/**.log', GLOB_BRACE) 在 7.2 下会返回空数组或 false,不是报错,所以容易被忽略。
PHP 7.2 下用 ** 匹配子目录,结果为空?
这是最典型的兼容性断裂点。PHP 7.2 的 glob() 完全不解析 **,它把整个模式当字面量去系统层匹配,自然找不到任何文件。
- ✅ 正确写法(7.2 兼容):
glob('/path/*.log')(仅当前层)或手写递归 +scandir() - ❌ 错误写法(7.2 失效):
glob('/path/**/*.log', GLOB_BRACE)—— 即使加了GLOB_BRACE也无效,因为**本身未被实现 - ⚠️ 注意:
GLOB_BRACE在 7.2 是可用的,但只支持{a,b,c}这类显式枚举,不负责**的语义
PHP 7.3+ 的 ** 行为与陷阱
7.3 起支持 **,但需同时满足两个条件:启用 GLOB_BRACE 标志,且模式中明确出现 **;否则仍按旧逻辑执行。
- ✅ 有效递归:
glob('/data/**/*.csv', GLOB_BRACE) - ❌ 无效递归:
glob('/data/**/*.csv')(缺GLOB_BRACE,7.3 下也退化为普通*) - ⚠️ 性能警告:
**会触发深度遍历,文件量大时比RecursiveDirectoryIterator更吃内存、更慢,别在日志归档脚本里无脑用
跨版本安全的替代方案
如果你的代码要同时跑在 7.2 和 7.3+,绕过 ** 是最稳妥的选择。用标准迭代器不依赖版本,还更可控。
立即学习“PHP免费学习笔记(深入)”;
- ✅ 推荐:
new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path, FilesystemIterator::SKIP_DOTS)),再用foreach遍历,配合pathinfo($file->getFilename(), PATHINFO_EXTENSION) === 'log'过滤 - ✅ 简单场景可降级:
scandir($path)+ 手动递归函数,明确控制深度和权限错误处理 - ❌ 别用
@glob()抑制错误——它掩盖false返回,导致后续foreach报Invalid argument supplied for foreach()
真正难调试的,是那些在 7.3 环境下跑通、一上 7.2 就静默失败的批量清洗脚本——因为 glob() 返回空数组而非异常,foreach 直接跳过,日志里连个提示都没有。



















