php批量重命名需用scandir()或glob()配合rename(),严格过滤非文件项、检查目标存在性、使用绝对路径,并针对windows中文名做编码转换或调用系统命令,同时捕获rename()返回值处理权限、路径、覆盖等错误。

用 rename() 遍历重命名最直接
PHP 没有内置的“批量重命名函数”,但用 scandir() + rename() 组合就能稳稳搞定。关键不是找轮子,而是控制好路径拼接和文件过滤,否则容易重命名失败或误伤目录。
常见错误是直接对 scandir() 返回的所有项调用 rename(),结果把 .、.. 甚至子目录也一起改了名。必须显式跳过非普通文件:
- 用
is_file()过滤,排除目录和特殊条目 - 重命名前用
file_exists()检查目标名是否已存在,避免覆盖 - 源路径和目标路径都建议用
realpath()或完整绝对路径,避免相对路径引发的rename(): No such file or directory
示例:把当前目录下所有 .txt 文件前加 backup_
$dir = __DIR__;
$files = scandir($dir);
foreach ($files as $filename) {
$path = $dir . '/' . $filename;
if (!is_file($path) || pathinfo($filename, PATHINFO_EXTENSION) !== 'txt') {
continue;
}
$newName = $dir . '/backup_' . $filename;
if (!file_exists($newName)) {
rename($path, $newName);
}
}
用 glob() 简化匹配逻辑
如果只处理特定后缀或命名模式(比如 *.log、img_*.jpg),glob() 比 scandir() 更干净——它天生返回匹配的文件路径数组,自动跳过目录和隐藏项(除非显式加 GLOB_HIDDEN)。
注意点:
-
glob()返回的是带路径的完整字符串,不是纯文件名,所以提取原文件名得用basename() - Windows 下路径分隔符要用
\或正斜杠/,统一用str_replace('\', '/', $path)更稳妥 - 若匹配结果为空数组,
foreach不会报错,但你要意识到没文件被处理——可加if (empty($matches)) { echo "未找到匹配文件"; }提示
示例:把 logs/ 下所有 .log 文件按日期重命名(如 app.log → app_20240520.log)
$date = date('Ymd');
$files = glob('logs/*.log');
foreach ($files as $oldPath) {
$info = pathinfo($oldPath);
$newPath = $info['dirname'] . '/' . $info['filename'] . '_' . $date . '.' . $info['extension'];
if (!file_exists($newPath)) {
rename($oldPath, $newPath);
}
}
重命名失败时的常见报错和应对
实际跑脚本时,rename() 失败不抛异常,只返回 false,必须手动检查。典型报错原因和对应动作:
-
rename(): Permission denied→ 当前 PHP 进程无写权限,用is_writable(dirname($target))提前校验 -
rename(): No such file or directory→ 源路径不存在或目标父目录不存在,用is_dir(dirname($target)) || mkdir(dirname($target), 0755, true)补目录 -
rename(): File exists→ 目标名已被占用,要么跳过、要么加序号(如$i = 1; while (file_exists($newPath)) { $newPath = str_replace('.', "_{$i}.", $newPath); $i++; })
别依赖 @rename() 抑制错误——掩盖问题比解决问题更危险。
Windows 下中文文件名要额外处理
在 Windows + PHP(尤其旧版本)中,直接用 rename() 处理含中文的文件名大概率失败,报错类似 Invalid argument。根本原因是 PHP 内部用 ANSI 编码处理路径,而中文文件名是 UTF-8。
解决办法只有两个:
- 用
mb_convert_encoding($filename, 'GBK', 'UTF-8')转码后再拼路径(仅限 Windows) - 更可靠的是换用
exec()调系统命令:exec("ren "{$oldName}" "{$newName}"");,但需确认exec未被禁用且 web 用户有 cmd 权限
Linux/macOS 一般无此问题,但跨平台脚本里建议加个 PHP_OS_FAMILY === 'Windows' 判断分支。
批量重命名真正难的不是语法,是路径安全、编码兼容、错误兜底这三块。漏掉任意一个,脚本就可能静默失败或破坏数据。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











