glob()批量重命名最稳妥,需检查rename()返回值、确保目标目录存在、处理路径编码及跨平台差异。

PHP用glob()批量获取文件再重命名最稳妥
直接遍历目录改名容易漏文件或误操作,glob()能按模式精准抓取目标文件,比scandir() + 手动过滤更可靠。注意它不递归,子目录要单独处理。
常见错误是没检查rename()返回值,失败时静默跳过,结果看似跑完了其实一个都没改成功。
-
glob()返回的是绝对路径还是相对路径,取决于你传入的模式,建议统一用__DIR__拼接避免路径混乱 - 新文件名里别含非法字符(如
/、\0),否则rename()直接报Warning: rename(): Invalid argument - Windows 下大小写不敏感,但Linux下
file.txt和FILE.TXT是两个文件,重命名时可能因同名冲突失败
用foreach循环+rename()实现安全替换
核心就是对每个匹配到的文件,生成新名字,再调用rename()。关键点在于:新路径必须完整,且目标目录得存在;否则会报No such file or directory。
下面这个例子把当前目录下所有.log文件名里的old替换成new:
立即学习“PHP免费学习笔记(深入)”;
foreach (glob(__DIR__ . '/*.log') as $oldPath) {
$oldName = basename($oldPath);
$newName = str_replace('old', 'new', $oldName);
$newPath = dirname($oldPath) . '/' . $newName;
if ($oldPath !== $newPath && !rename($oldPath, $newPath)) {
error_log("Failed to rename: " . $oldPath);
}
}
批量替换含序号的文件名(比如日志轮转)
如果要重命名成access_001.log、access_002.log这种带自增序号的格式,不能只靠str_replace(),得先统计数量再构造新名,否则并发执行或多次运行会撞名。
更稳妥的做法是先收集全部待处理文件,排序后再逐个编号:
- 用
array_values(array_filter(glob(...)))确保索引连续 - 用
sprintf('%03d', $index + 1)保证三位数补零 - 如果原文件名本身含数字(如
app_v2.log),str_replace('v2', 'v3')比正则更轻量,除非你要提取并递增数字
Windows下中文文件名重命名失败怎么办
PHP默认用ISO-8859-1处理文件系统调用,Windows命令行又常是GBK,导致中文路径rename()失败,报错类似Cannot rename file: No error但实际没反应。
解决方法只有两个:
- 在脚本开头加
mb_internal_encoding('UTF-8');,并确保PHP运行环境支持UTF-8文件系统(PHP 7.1+ 默认支持) - 更通用的办法:用
iconv('UTF-8', 'GBK', $path)临时转码(仅限Windows),但要注意iconv()可能抛出异常,需try/catch
Mac/Linux一般无此问题,但NFS挂载的Windows共享目录仍可能触发编码问题,这时候得看挂载参数是否带iocharset=utf8。











