跳转到主内容
websoft网络软件专家 - 深耕网络技术,打造实用软件!

PHP文件系统遍历与搜索教程

PHP遍历文件系统需据场景选方法:scandir()适合单层但需过滤.和..;递归首选RecursiveDirectoryIterator+RecursiveIteratorIterator;glob()内存开销大且跨平台问题多;opendir()/readdir()省内存但需防句柄泄漏。 PHP里遍历文件系统不是选“最短代码”,而是看场景:要单层还是递归?要过滤扩展名还是按权限跳过?内存是否受限?用错方法可能卡死或漏掉文件。 scandir() 适合单层快速列举,但必须手动处理 . 和 .. 它返回的是包含所有条目的数组,包括
.
和
..
,不加过滤直接传给
is_file()
或拼路径会出错。 用
array_filter($files, fn($f) => $f !== '.' && $f !== '..')
去掉特殊项 排序默认是字典序,
file10.txt
会排在
file2.txt
前面;需要自然排序就加
natcasesort($files)
路径拼接必须用
DIRECTORY_SEPARATOR
或
realpath()
,硬写
/
在 Windows 下会失效 不递归,想进子目录得自己写递归调用,容易栈溢出或无限循环(比如符号链接成环) RecursiveDirectoryIterator + RecursiveIteratorIterator 是递归首选 这是 PHP 官方推荐的递归方式,比手写递归健壮得多,自动跳过不可读目录(只要加
try/catch
),也支持
SKIP_DOTS
标志省去手动过滤。 初始化时传
FilesystemIterator::SKIP_DOTS
,
.
和
..
就不会出现在迭代中 用
$file->isFile()
判断类型,别用
is_file($file->getPathname())
—— 后者可能因权限失败而返回 false,误判为非文件 遇到
Permission denied
会抛
UnexpectedValueException
,必须用
try/catch
包裹
foreach
,否则整个遍历中断 如果只需要文件(不含目录),构造
RecursiveIteratorIterator
时第三个参数用
RecursiveIteratorIterator::LEAVES_ONLY
glob() 看似简洁,但只适合小目录+固定模式
glob()
是一次性加载全部匹配结果到内存的,对含几千个文件的目录,很容易触发
memory_limit
或超时。它也不原生支持深度递归(
GLOB_BRACE
或
**
依赖系统 libc,跨平台行为不一致)。 PHP 8.5.5 PHP 8.5.5 是 PHP 8.5 分支的维护更新版本。该版本延续了“小步快跑”的迭代逻辑,通过深度错误修复、底层性能微调以及安全加固,旨在为开发者提供一个更健壮、更高效的运行环境。该版本严格遵守语义化版本规范,不包含破坏性变更。 下载 立即学习 “ PHP免费学习笔记(深入) ”; 模式里写
$dir . '/*.php'
没问题,但写
$dir . '/**/*.php'
在部分 PHP 版本或系统上会静默失败 无法跳过无权限目录,
glob()
遇到
/proc
类路径直接返回空数组,不报错也不提示,容易误以为“没文件” 返回的是纯路径字符串数组,没有元信息(如修改时间、大小),后续要查得再
stat()
一次,IO 开销翻倍 不能和
is_readable()
结合做前置检查——
glob()
本身不校验可读性 opendir() + readdir() 适合内存敏感场景,但易漏资源释放 它不预加载全部条目,边读边处理,内存占用稳定,适合遍历超大目录(比如日志归档目录)。但忘了
closedir()
会导致句柄泄漏,尤其在长生命周期脚本(如 CLI 守护进程)中会累积。 每次
readdir()
返回的是相对名,拼完整路径前先用
is_dir()
或
is_file()
判断,避免对
.
/
..
调用
stat()
循环里不要在
readdir()
条件中直接写
is_file($path . '/' . $f)
,万一
$f
是空字符串或非法字符会出错 PHP 8.1+ 支持
Dir
类替代
opendir()
,语法更干净:
$dir = dir($path); while (($f = $dir->read()) !== false) { ... } $dir->close();
Windows 下注意路径长度限制(MAX_PATH=260),长路径要用
\?
前缀,
opendir()
不支持,得换
RecursiveDirectoryIterator
真正麻烦的不是“怎么写”,而是权限异常、符号链接循环、超长路径、编码不一致(比如 FTP 上传的 UTF-8 文件名在某些 locale 下
scandir()
返回乱码)——这些情况在测试环境常被忽略,上线后才暴露。

相关文章