recursivedirectoryiterator更稳,因其内置跳过./..、自动处理符号链接且不跟随,比手写scandir()递归更可靠,但需try/catch捕获permission denied异常。

递归遍历目录时,scandir() 和 RecursiveDirectoryIterator 哪个更稳?
用 scandir() 手写递归容易漏掉 . 和 ..,还可能因权限问题中断;RecursiveDirectoryIterator 内置跳过点文件、自动处理符号链接(默认不跟随),更可靠。但要注意:它默认不递归进入不可读目录(比如 Permission denied 会抛 UnexpectedValueException),必须包在 try/catch 里。
实操建议:
- 优先用
RecursiveDirectoryIterator+RecursiveIteratorIterator组合,比手写scandir()+is_dir()更少出错 - 加
FilesystemIterator::SKIP_DOTS显式跳过./.. - 对每个
RegexIterator或手动is_file()判断后再处理,避免把目录当文件打开
替换文件内容前,为什么必须先 file_get_contents() 再 file_put_contents()?
PHP 没有原地替换文件内容的原子操作。直接 fopen(..., 'r+') + fwrite() 极易破坏文件(比如新内容比旧内容短,残留尾部旧数据)。稳妥做法是:读全量 → 替换 → 写入新内容。
注意点:
- 大文件慎用
file_get_contents(),可能 OOM;如需处理 >10MB 文件,改用流式读写(fopen+fgets分块) - 替换后写入前,建议用
file_put_contents($path, $content, LOCK_EX)加锁,防并发写冲突 - 务必检查
file_put_contents()返回值 —— 失败时返回false,不是字节数
preg_replace() 替换时,路径中反斜杠和正则特殊字符怎么逃逸?
Windows 路径含反斜杠(),而 preg_replace() 把 当转义符;同时搜索字符串若含 .、*、$ 等,会被正则引擎误解析。不能直接把路径拼进正则模式。
正确做法:
- 用
preg_quote($search, '/')对搜索字符串整体转义,第二个参数填你实际用的定界符(如/) - Windows 下路径分隔符统一转成正斜杠再处理(
str_replace('\', '/', $path)),避免正则里出现\混淆 - 如果只是字面量替换(非正则),直接用
str_replace()更安全、更快 —— 别硬套preg_replace()
执行替换时,如何避免把 .git/、vendor/ 这类目录也扫进去?
递归迭代器默认遍历所有子目录,但项目里常要排除特定目录(如版本控制、依赖包)。不能靠后过滤文件路径字符串(效率低且易漏),得在迭代器层面剪枝。
推荐方案:
- 用
CallbackFilterIterator包裹RecursiveIteratorIterator,在accept()回调里判断$current->getPathname()是否匹配排除规则 - 排除逻辑写成白名单更安全(比如只处理
.php、.js、.html),比黑名单更可控 - 注意:排除判断必须用完整路径(
$current->getPathname()),不能只看getFilename(),否则无法区分src/config.php和tests/config.php
真正麻烦的是跨编码文件(如 GBK 的老 HTML)和 BOM 头 —— file_get_contents() 默认按 UTF-8 读,一读就乱码,替换结果全毁。这种场景必须先 mb_detect_encoding() 探测,再 mb_convert_encoding() 统一转码,否则连“搜索成功”都是假象。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











