file_get_contents + file_put_contents 是最稳妥的批量文本替换方式,需统一编码、处理换行、小文件适用;大文件用流式处理;递归遍历须用 RecursiveDirectoryIterator;重命名要 pathinfo 拆解;禁用不安全 exec;务必备份与错误校验。

PHP批量修改目录下文件内容用 file_get_contents + file_put_contents
直接读取再写回是最稳妥的批量文本替换方式,适合配置文件、模板、日志等纯文本场景。
常见错误是忽略编码和换行符差异,导致 Windows 编辑的文件在 Linux 下执行后乱码或空行增多。
- 务必用
mb_convert_encoding统一源文件编码(如mb_convert_encoding($content, 'UTF-8', 'GBK')) - 替换前先
trim()再操作,避免前后空白干扰正则或字符串匹配 - 对大文件(>10MB)要改用
fopen/fgets流式处理,否则内存溢出 - 示例:把所有
.php文件里的old_function()替成new_function()
$files = glob(__DIR__ . '/src/*.php');
foreach ($files as $file) {
$content = file_get_contents($file);
$content = str_replace('old_function()', 'new_function()', $content);
file_put_contents($file, $content);
}递归遍历子目录必须用 RecursiveDirectoryIterator
用 glob(__DIR__ . '/**/*.php') 看似简洁,但在 PHP 5.6 或某些系统(如旧版 macOS)上不支持双星号,会漏掉子目录。
真正跨版本可靠的方案是迭代器组合:
立即学习“PHP免费学习笔记(深入)”;
-
RecursiveDirectoryIterator负责逐层进入目录 -
RecursiveIteratorIterator展平为线性列表 - 配合
RegexIterator或手动pathinfo()过滤扩展名 - 注意跳过
.和..,也别误改.git或vendor目录
$it = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator(__DIR__)
);
foreach ($it as $file) {
if ($file->isFile() && $file->getExtension() === 'php') {
// 处理逻辑
}
}批量重命名文件名别硬拼字符串,用 pathinfo 拆解再组装
直接 str_replace('old_', 'new_', $filename) 容易误伤路径或扩展名,比如把 old_style.css 改成 new_style.cnew_s。
安全做法永远基于结构拆解:
- 用
pathinfo($filepath)拿到dirname、basename、extension、filename - 只对
filename做逻辑替换,再用dirname+ 新filename+extension拼新路径 - 调用
rename()前先file_exists()检查目标是否已存在,避免覆盖 - Windows 下大小写不敏感,但 Linux 敏感——
Readme.md重命名为README.md在 Linux 会失败,需先删原文件
用 exec() 调系统命令要防 shell 注入和路径空格
有人图快写 exec("sed -i 's/old/new/g' " . $file),但 $file 含空格或单引号时直接崩,且 Windows 不支持 sed。
如果真要用系统命令,必须:
- Linux/macOS 下用
escapeshellarg($file)包裹每个路径参数 - 避免拼接用户输入,尤其是从
$_GET或文件名里提取的变量 - Windows 用户想用
PowerShell,得先检测php_uname('s'),再选Get-ChildItem+ForEach-Object方案 - 更稳妥的是放弃 exec,回到 PHP 原生文件操作——毕竟批量改文件本就不需要依赖外部命令
真正难的不是“怎么改”,而是改之前没备份、没判断权限、没校验结果。哪怕只是 file_put_contents,也要加 if (false === $bytes) { /* 记录失败 */ } ——否则静默失败,第二天才发现整站配置全错了。











