scandir()最轻量但需剔除.和..并重置键名;递归必须用recursivedirectoryiterator而非手写;glob()不跨平台且不递归;判断类型须用is_file()/is_dir()而非扩展名;错误处理要细化到每个文件项。

用 scandir() 遍历目录最直接,但要注意返回的 . 和 ..
scandir() 是 PHP 原生最轻量的目录读取方式,返回包含所有文件名(含子目录)的数组。但它一定会包含当前目录 . 和父目录 ..,不剔除会导致后续操作出错,比如 is_file() 判断失败或递归时无限跳转。
实操建议:
- 用
array_diff()剔除.和..:scandir($path)→array_diff(scandir($path), ['.', '..']) - 结果是索引数组,需用
array_values()重置键名,否则遍历时键可能不连续 - 它不递归,只读一级内容;若要全路径,得手动拼接:
$fullPath = $path . '/' . $file - 注意路径末尾斜杠:Windows 下
要转义或统一用/,推荐用dirname(__FILE__) . '/mydir'构造绝对路径
递归遍历必须用 RecursiveDirectoryIterator,别手写递归函数
自己用 scandir() + foreach + is_dir() 写递归容易漏掉权限错误、符号链接死循环、或跳过隐藏文件。PHP 标准库的 RecursiveDirectoryIterator 已处理这些边界情况,且支持过滤、跳过、异常捕获。
实操建议:
- 基础用法:
new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path)),它会自动展开所有子目录 - 想跳过
.git或node_modules?加FilesystemIterator::SKIP_DOTS并配合accept()方法自定义过滤逻辑 - 遇到无权限目录时默认抛
UnexpectedValueException,需用try/catch包裹迭代过程 - 获取完整路径用
$item->getPathname(),不是$item->__toString()—— 后者只返回文件名
glob() 适合简单匹配,但不支持递归通配符(**)在旧 PHP 版本中不可靠
glob() 写起来短,比如 glob('/path/*.php') 拿所有 PHP 文件。但它本质是 shell 风格匹配,不走迭代器,也不检查文件类型,返回的就是纯路径数组。
实操建议:
- PHP 7.1+ 支持
GLOB_BRACE和GLOB_ONLYDIR,但glob('/path/**/*', GLOB_BRACE | GLOB_ONLYDIR)在 Windows 或某些 Linux libc 下行为不一致,别依赖** - 要跨平台安全递归,改用
RecursiveDirectoryIterator+RegexIterator过滤后缀更稳 -
glob()对不存在目录静默返回空数组,不会报错;但若路径含未转义的[、?等字符,会误匹配或返回空,先escapeshellarg()不适用,应改用str_replace(['[', ']', '?'], ['[', ']', '?'], $path)
判断文件类型别只信扩展名,is_file() 和 is_dir() 必须配合使用
遍历时常见错误是看到 config.json 就当它是文件,结果其实是同名符号链接指向目录,或权限不足导致 stat() 失败。仅靠字符串匹配或 file_exists() 不够可靠。
实操建议:
- 对每个条目先调
is_file($path)或is_dir($path),而不是查pathinfo($path, PATHINFO_EXTENSION) - 如果用了
RecursiveDirectoryIterator,直接调$item->isFile()或$item->isDir(),它已缓存stat结果,比重复调用函数快 - 注意:
is_link()返回 true 时,is_file()和is_dir()可能都为 false,需单独处理符号链接逻辑 - Windows 下长路径(>260 字符)可能导致
is_*()返回 false,此时应改用realpath()前置处理或启用 PHP 的\?前缀支持
RecursiveDirectoryIterator 时务必包一层 try/catch,并在 catch 里记录具体路径和 $e->getMessage()。php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











