最快获取当前目录文件名数组用scandir(),需array_diff过滤'.', '..';递归遍历推荐RecursiveDirectoryIterator+RecursiveIteratorIterator并启用SKIP_DOTS和LEAVES_ONLY标志。

用 scandir() 最快拿到当前目录文件名数组
直接调用 scandir() 是 PHP 里最轻量、最常用的起步方式,它不递归,只读一层,返回包含 . 和 .. 的完整文件/目录名列表。
常见错误是拿到结果后直接遍历输出,却没过滤掉 . 和 ..,导致后续操作报错或逻辑错乱。
- 用
array_diff()剔除:scandir($path)结果传给array_diff($list, ['.', '..']) - 注意返回值是字符串数组,不是
DirectoryIterator对象,没法直接查文件类型或大小 - Windows 下路径分隔符不影响,但拼接子路径时建议统一用
/或DIRECTORY_SEPARATOR
递归遍历必须用 RecursiveDirectoryIterator + RecursiveIteratorIterator
要真正“所有文件”,就得递归。PHP 原生推荐走 SPL 迭代器路线,比手写递归函数更稳、内存更可控。
容易踩的坑是只 new 了 RecursiveDirectoryIterator 就开始 foreach —— 它默认跳过子目录,必须套一层 RecursiveIteratorIterator 才能展开。
- 初始化时加标志位:
new RecursiveDirectoryIterator($path, FilesystemIterator::SKIP_DOTS),自动过滤.和.. - 外层包装用:
new RecursiveIteratorIterator($it, RecursiveIteratorIterator::LEAVES_ONLY),确保只吐文件,不吐空目录 - 迭代器返回的是
SplFileInfo对象,可直接调getRealPath()、isFile()、getSize()
glob() 适合带通配符的简单筛选,但不跨平台
如果只要 *.php 或 config/*.yaml 这类明确模式的文件,glob() 写起来最短,一行搞定。
但它在 Windows 和 Linux 下对大小写敏感性不同:Linux 默认区分,Windows 不区分;而且不支持 ** 深层递归(PHP 8.1+ 才通过 GLOB_BRACE 有限支持)。
- 安全起见,对用户输入的路径必须先
realpath()校验,再进glob(),否则可能绕过预期目录 - 返回空数组不等于出错,可能是没匹配到,得用
!empty($files)判断,而不是=== false - 避免在大目录下用
glob('*'),它底层仍是scandir()+ 字符串匹配,性能不如直接迭代器
遍历中判断文件类型别只信扩展名
很多人用 pathinfo($file, PATHINFO_EXTENSION) 做类型过滤,但扩展名可伪造,真实场景中常遇到无扩展名脚本、或 .htaccess 这类隐藏配置文件被漏掉。
真正可靠的判断得靠文件内容或系统属性,PHP 提供了几个低开销手段:
-
$fileInfo->isFile()比is_file($path)略快,因对象已缓存 stat 信息 - 需要 MIME 类型?用
finfo_open(FILEINFO_MIME_TYPE)+finfo_file(),但别对每个文件都新开 handle,复用一个即可 - 忽略符号链接?构造
RecursiveDirectoryIterator时传FilesystemIterator::FOLLOW_SYMLINKS反而危险,建议默认不跟,用is_link()单独处理
实际项目里,90% 的需求用 RecursiveDirectoryIterator 套两层就能稳住;剩下那 10%,往往是没意识到 SKIP_DOTS 和 LEAVES_ONLY 这两个标志位缺一不可。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











