本文目录导读:

我来介绍几种批量替换文件名的脚本方法,涵盖不同场景和需求。
Python 脚本(最灵活)
基础版 - 简单替换
import os
from pathlib import Path
def batch_rename(directory, old_str, new_str):
"""
批量替换文件名中的指定字符串
Args:
directory: 目标目录
old_str: 要替换的旧字符串
new_str: 替换成的新字符串
"""
dir_path = Path(directory)
for file_path in dir_path.iterdir():
if file_path.is_file():
# 生成新文件名
new_name = file_path.name.replace(old_str, new_str)
# 如果有变化则重命名
if new_name != file_path.name:
new_path = file_path.with_name(new_name)
file_path.rename(new_path)
print(f"重命名: {file_path.name} → {new_name}")
# 使用示例
batch_rename("./my_files", "2023", "2024")
进阶版 - 使用正则表达式
import os
import re
from pathlib import Path
def regex_rename(directory, pattern, replacement, recursive=False):
"""
使用正则表达式批量替换文件名
Args:
directory: 目标目录
pattern: 正则表达式模式
replacement: 替换字符串(支持反向引用如 \1)
recursive: 是否递归子目录
"""
dir_path = Path(directory)
files = dir_path.rglob("*") if recursive else dir_path.iterdir()
for file_path in files:
if file_path.is_file():
try:
# 使用正则替换
new_name = re.sub(pattern, replacement, file_path.name)
if new_name != file_path.name:
new_path = file_path.with_name(new_name)
file_path.rename(new_path)
print(f"重命名: {file_path.name} → {new_name}")
except Exception as e:
print(f"处理 {file_path.name} 出错: {e}")
# 使用示例
# 将文件名中的数字改为下划线格式
regex_rename("./files", r"(\d{4})-(\d{2})-(\d{2})", r"\1年\2月\3日", recursive=True)
高级版 - 添加序号和格式处理
import os
from pathlib import Path
class BatchRenamer:
def __init__(self, directory):
self.directory = Path(directory)
def add_prefix(self, prefix, ext_filter=None):
"""给文件名添加前缀"""
for file in self._get_files(ext_filter):
new_name = f"{prefix}{file.name}"
self._rename(file, new_name)
def add_suffix(self, suffix, ext_filter=None):
"""给文件名添加后缀(在扩展名之前)"""
for file in self._get_files(ext_filter):
stem = file.stem
new_name = f"{stem}{suffix}{file.suffix}"
self._rename(file, new_name)
def add_sequence(self, start=1, digits=3, ext_filter=None):
"""给文件名添加序号"""
for i, file in enumerate(self._get_files(ext_filter), start):
seq = str(i).zfill(digits)
new_name = f"{seq}_{file.name}"
self._rename(file, new_name)
def change_extension(self, new_ext, ext_filter=None):
"""修改文件扩展名"""
for file in self._get_files(ext_filter):
new_name = f"{file.stem}.{new_ext}"
self._rename(file, new_name)
def _get_files(self, ext_filter):
"""获取符合条件的文件列表"""
files = [f for f in self.directory.iterdir() if f.is_file()]
if ext_filter:
if isinstance(ext_filter, str):
ext_filter = [ext_filter]
files = [f for f in files if f.suffix.lstrip('.') in ext_filter]
return files
def _rename(self, file, new_name):
"""执行重命名操作"""
if file.name != new_name:
new_path = file.with_name(new_name)
if new_path.exists():
print(f"跳过 {file.name}: 目标文件已存在")
else:
file.rename(new_path)
print(f"重命名: {file.name} → {new_name}")
# 使用示例
renamer = BatchRenamer("./my_files")
# 添加前缀
renamer.add_prefix("2024_")
# 添加序号(只处理txt文件)
renamer.add_sequence(start=1, digits=4, ext_filter="txt")
# 修改扩展名
renamer.change_extension("bak", ext_filter=["txt", "doc"])
Bash/Shell 脚本(Linux/Mac)
基础版
#!/bin/bash
# 批量替换文件名
replace_in_names() {
local directory="$1"
local old_str="$2"
local new_str="$3"
for file in "$directory"/*; do
if [ -f "$file" ]; then
filename=$(basename "$file")
new_filename="${filename//$old_str/$new_str}"
if [ "$filename" != "$new_filename" ]; then
mv "$file" "$directory/$new_filename"
echo "重命名: $filename → $new_filename"
fi
fi
done
}
# 使用示例
replace_in_names "./files" "old" "new"
高级版 - 带参数和错误处理
#!/bin/bash
usage() {
echo "用法: $0 [-d 目录] [-o 旧字符串] [-n 新字符串] [-s 序号开始]"
echo "示例: $0 -d ./files -o old -n new"
echo " $0 -d ./files -s 1"
exit 1
}
# 解析参数
while getopts "d:o:n:s:" opt; do
case $opt in
d) DIRECTORY="$OPTARG" ;;
o) OLD_STR="$OPTARG" ;;
n) NEW_STR="$OPTARG" ;;
s) SEQUENCE="$OPTARG" ;;
*) usage ;;
esac
done
# 检查参数
if [ -z "$DIRECTORY" ]; then
echo "错误: 请指定目录"
usage
fi
if [ ! -d "$DIRECTORY" ]; then
echo "错误: 目录不存在"
exit 1
fi
# 执行重命名
if [ -n "$OLD_STR" ] && [ -n "$NEW_STR" ]; then
# 执行替换
for file in "$DIRECTORY"/*; do
if [ -f "$file" ]; then
filename=$(basename "$file")
new_filename="${filename//$OLD_STR/$NEW_STR}"
if [ "$filename" != "$new_filename" ]; then
if [ -f "$DIRECTORY/$new_filename" ]; then
echo "警告: 目标文件存在,跳过 $filename"
else
mv "$file" "$DIRECTORY/$new_filename"
echo "重命名: $filename → $new_filename"
fi
fi
fi
done
elif [ -n "$SEQUENCE" ]; then
# 添加序号
count=$SEQUENCE
for file in "$DIRECTORY"/*; do
if [ -f "$file" ]; then
filename=$(basename "$file")
# 使用3位数字补零
seq=$(printf "%03d" $count)
new_filename="${seq}_${filename}"
mv "$file" "$DIRECTORY/$new_filename"
echo "重命名: $filename → $new_filename"
((count++))
fi
done
else
usage
fi
echo "完成!"
Windows Batch 脚本
Windows批处理
@echo off
setlocal enabledelayedexpansion
echo ==================================
echo 批量文件名替换工具
echo ==================================
set /p directory=请输入目录路径:
set /p old_str=请输入要替换的字符:
set /p new_str=请输入新字符:
if not exist "%directory%" (
echo 目录不存在!
pause
exit /b
)
cd /d "%directory%"
for %%f in (*.*) do (
set "filename=%%~nf"
set "extension=%%~xf"
rem 替换文件名
set "newfilename=!filename:%old_str%=%new_str%!"
rem 检查是否有变化
if not "!filename!"=="!newfilename!" (
ren "%%f" "!newfilename!!extension!"
echo 重命名: %%f → !newfilename!!extension!
)
)
echo.
echo 操作完成!
pause
PowerShell 脚本(Windows)
# PowerShell 批量重命名脚本
param(
[string]$Path = ".",
[string]$OldString,
[string]$NewString,
[switch]$Recursive,
[switch]$WhatIf # 预览模式
)
function Rename-Files {
$files = if ($Recursive) {
Get-ChildItem -Path $Path -File -Recurse
} else {
Get-ChildItem -Path $Path -File
}
foreach ($file in $files) {
$newName = $file.Name.Replace($OldString, $NewString)
if ($file.Name -ne $newName) {
$newPath = Join-Path $file.DirectoryName $newName
if ($WhatIf) {
Write-Host "预览: $($file.Name) → $newName" -ForegroundColor Yellow
} else {
try {
Move-Item -Path $file.FullName -Destination $newPath -ErrorAction Stop
Write-Host "已重命名: $($file.Name) → $newName" -ForegroundColor Green
} catch {
Write-Warning "重命名失败: $($file.Name) - $_"
}
}
}
}
}
# 使用预检查
Write-Host "开始处理..." -ForegroundColor Cyan
Rename-Files
if (-not $WhatIf) {
Write-Host "完成!" -ForegroundColor Green
}
Node.js 脚本
#!/usr/bin/env node
const fs = require('fs');
const path = require('path');
const readline = require('readline');
// 创建命令行交互
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
function batchRename(directory, oldStr, newStr, options = {}) {
const files = fs.readdirSync(directory);
files.forEach((filename) => {
const filePath = path.join(directory, filename);
// 检查是否为文件
if (fs.statSync(filePath).isFile()) {
// 检查扩展名过滤
if (options.exts && !options.exts.some(ext => filename.endsWith(ext))) {
return;
}
// 替换文件名
const newFilename = filename.replace(oldStr, newStr);
// 执行重命名
if (filename !== newFilename) {
const newPath = path.join(directory, newFilename);
if (fs.existsSync(newPath)) {
console.log(`跳过 ${filename}: 目标文件已存在`);
} else {
fs.renameSync(filePath, newPath);
console.log(`重命名: ${filename} → ${newFilename}`);
}
}
}
});
}
// 命令行交互
rl.question('请输入目录路径: ', (directory) => {
rl.question('请输入要替换的字符串: ', (oldStr) => {
rl.question('请输入新字符串: ', (newStr) => {
rl.question('是否限制扩展名? (y/n): ', (answer) => {
if (answer.toLowerCase() === 'y') {
rl.question('请输入扩展名(用逗号分隔): ', (extsInput) => {
const exts = extsInput.split(',').map(e => e.trim());
batchRename(directory, oldStr, newStr, { exts });
console.log('完成!');
rl.close();
});
} else {
batchRename(directory, oldStr, newStr);
console.log('完成!');
rl.close();
}
});
});
});
});
使用建议
- 先备份:批量操作前务必备份重要文件
- 预览功能:尽量使用带预览功能的脚本(如 -WhatIf 参数)
- 测试环境:先用测试目录验证脚本逻辑
- 异常处理:脚本应包含错误处理和冲突检查
- 日志记录:保存重命名记录,便于追踪和撤销
快速使用示例
Python 一行命令示例:
# 在命令行直接运行
python -c "import os; [os.rename(f, f.replace('old', 'new')) for f in os.listdir('.') if 'old' in f]"
Bash 一行命令示例:
# 替换当前目录下所有文件的old为new
for f in *; do [ -f "$f" ] && mv "$f" "${f//old/new}"; done
选择哪种脚本取决于你的:
- 操作系统
- 文件量大小
- 操作复杂度
- 是否需要交互界面
建议先从简单的版本开始测试,确认无误后再批量执行。