您的位置:首页 >PHP递归遍历目录方法详解
发布于2026-02-23 阅读(0)
扫一扫,手机访问
scandir递归需手动过滤'.','..'并校验权限,否则易无限递归或Permission denied;RecursiveIterator自动跳过点文件且更安全,但默认静默忽略不可读目录,性能上scandir略快但容错差。

直接用 scandir 做递归,必须手动过滤 . 和 ..,否则会无限递归或跳进上级目录。PHP 7.4+ 虽然加了 SCANDIR_SORT_NONE 选项,但不影响路径逻辑——它只控制排序,不解决递归边界问题。
常见错误现象:Warning: scandir(): Failed to open dir: Permission denied 或遍历结果里混入 ./config 这种相对路径,导致 is_dir() 判断失败。
scandir 后,用 array_diff($files, ['.', '..']) 清洗结果realpath($dir . DIRECTORY_SEPARATOR . $file) 或至少 $dir . '/' . $file(Windows 下 DIRECTORY_SEPARATOR 更稳妥)is_dir() + is_readable() 双重检查,避免权限错误中断流程RecursiveIterator 系列(比如 RecursiveDirectoryIterator + RecursiveIteratorIterator)本质是封装好的树形遍历器,不用手动处理 ./..,也不容易写错路径拼接。但它默认跳过不可读目录——不是报错,而是静默忽略,这点容易被当成“没遍历到”。
使用场景:需要稳定遍历、支持过滤、或后续要对接 FilterIterator 做条件筛选(比如只取 .php 文件)。
RecursiveDirectoryIterator 时传 FilesystemIterator::SKIP_DOTS,比默认行为更明确RecursiveIteratorIterator 的第二个参数决定遍历深度,RecursiveIteratorIterator::SELF_FIRST 是常用值;用 LEAVES_ONLY 会跳过目录本身,只返回文件getChildren() 并再次 foreach —— 它会破坏当前迭代器状态,导致跳过条目或 Invalid argument supplied for foreach()小目录(<1000 个文件)两者差别不大;但目录嵌套深、单层文件多时,scandir 手动递归通常更快——因为没对象创建开销,且能按需跳过子目录。而 RecursiveIterator 在初始化时就会尝试读取所有层级的目录结构,遇到权限不足的目录会直接停止该分支,但前期仍做了不少无效探测。
兼容性影响:PHP 5.3+ 支持 RecursiveIterator,但某些旧环境(如部分共享主机)禁用了 RecursiveDirectoryIterator 的 glob:// 尝试逻辑,表现为无法进入某些符号链接目录。
scandir + foreach 组合更轻量mtime、size 或做 isLink() 判断,RecursiveDirectoryIterator 返回的 SplFileInfo 对象更省事RecursiveIteratorIterator 默认不抛异常,要用 setFlags(RecursiveIteratorIterator::CATCH_GET_CHILD) 才能在子目录出错时继续主循环中文路径在 scandir 下可能返回乱码(尤其 Windows + GBK 环境),而 RecursiveDirectoryIterator 内部用 UTF-8 处理,表现更一致。但两者对符号链接都默认跟随——也就是说,is_dir() 返回 true 的可能是软链指向的目录,不是原始路径本身。
这会导致两个问题:一是遍历路径重复(软链指向已遍历过的目录),二是统计磁盘占用时误算。
lstat() 替代 stat() 或 is_dir() 来判断是否为符号链接,再决定是否跳过realpath()(非原始路径),防止软链循环引用RecursiveDirectoryIterator::FOLLOW_SYMLINKS 构造参数控制是否跟随,之前版本只能靠 is_link() + 手动跳过上一篇:360安全浏览器官网入口地址
下一篇:宙斯浏览器官网入口及访问指南
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
9