本文目录导读:

我来为你编写一个批量给文件加前缀并创建清单的脚本。
Python版本(推荐)
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
批量给文件添加前缀并生成清单脚本
支持:自定义前缀、文件筛选、清单格式选择
"""
import os
import sys
import argparse
from datetime import datetime
import csv
import json
class FilePrefixManager:
def __init__(self, folder_path, prefix, extensions=None, recursive=False):
"""
初始化
:param folder_path: 文件夹路径
:param prefix: 要添加的前缀
:param extensions: 文件扩展名筛选列表,如 ['.txt', '.jpg']
:param recursive: 是否递归子文件夹
"""
self.folder_path = folder_path
self.prefix = prefix
self.extensions = extensions
self.recursive = recursive
self.changed_files = []
self.failed_files = []
self.skipped_files = []
def get_all_files(self):
"""获取所有符合条件的文件"""
all_files = []
if self.recursive:
# 递归遍历所有子文件夹
for root, dirs, files in os.walk(self.folder_path):
for file in files:
full_path = os.path.join(root, file)
if self.check_extension(file):
all_files.append(full_path)
else:
# 只处理当前文件夹的文件
for file in os.listdir(self.folder_path):
full_path = os.path.join(self.folder_path, file)
if os.path.isfile(full_path) and self.check_extension(file):
all_files.append(full_path)
return sorted(all_files)
def check_extension(self, filename):
"""检查文件扩展名是否在筛选列表中"""
if not self.extensions:
return True # 不筛选,返回所有文件
ext = os.path.splitext(filename)[1].lower()
return ext in [e.lower() for e in self.extensions]
def add_prefix(self, file_path):
"""给单个文件添加前缀"""
try:
dir_name = os.path.dirname(file_path)
old_name = os.path.basename(file_path)
new_name = self.prefix + old_name
new_path = os.path.join(dir_name, new_name)
# 检查新文件是否已存在
if os.path.exists(new_path):
self.skipped_files.append({
'原文件': old_name,
'原因': f'目标文件已存在: {new_name}'
})
return False
os.rename(file_path, new_path)
self.changed_files.append({
'原文件名': old_name,
'新文件名': new_name,
'完整路径': new_path,
'处理时间': datetime.now().strftime('%Y-%m-%d %H:%M:%S')
})
return True
except Exception as e:
self.failed_files.append({
'文件名': os.path.basename(file_path),
'错误原因': str(e)
})
return False
def process_all_files(self):
"""处理所有文件"""
all_files = self.get_all_files()
print(f"找到 {len(all_files)} 个待处理文件")
for file_path in all_files:
self.add_prefix(file_path)
return True
def generate_manifest(self, format_type='txt'):
"""
生成清单文件
:param format_type: txt, csv, json
"""
timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
manifest_file = os.path.join(self.folder_path, f'文件清单_{timestamp}.{format_type}')
data = {
'生成时间': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
'前缀': self.prefix,
'文件夹': self.folder_path,
'统计': {
'成功': len(self.changed_files),
'失败': len(self.failed_files),
'跳过': len(self.skipped_files)
},
'处理明细': {
'成功列表': self.changed_files,
'失败列表': self.failed_files,
'跳过列表': self.skipped_files
}
}
if format_type == 'txt':
with open(manifest_file, 'w', encoding='utf-8') as f:
f.write("=" * 60 + "\n")
f.write(f"文件清单生成时间:{data['生成时间']}\n")
f.write(f"添加前缀:{data['前缀']}\n")
f.write(f"处理文件夹:{data['文件夹']}\n")
f.write(f"成功处理:{data['统计']['成功']} 个文件\n")
f.write(f"处理失败:{data['统计']['失败']} 个文件\n")
f.write(f"跳过文件:{data['统计']['跳过']} 个文件\n")
f.write("=" * 60 + "\n\n")
if self.changed_files:
f.write("成功处理的文件:\n")
f.write("-" * 40 + "\n")
for item in self.changed_files:
f.write(f"原文件名:{item['原文件名']}\n")
f.write(f"新文件名:{item['新文件名']}\n")
f.write(f"处理时间:{item['处理时间']}\n")
f.write("-" * 40 + "\n")
if self.failed_files:
f.write("\n处理失败的文件:\n")
f.write("-" * 40 + "\n")
for item in self.failed_files:
f.write(f"文件名:{item['文件名']}\n")
f.write(f"错误原因:{item['错误原因']}\n")
f.write("-" * 40 + "\n")
if self.skipped_files:
f.write("\n跳过的文件:\n")
f.write("-" * 40 + "\n")
for item in self.skipped_files:
f.write(f"原文件:{item['原文件']}\n")
f.write(f"原因:{item['原因']}\n")
f.write("-" * 40 + "\n")
elif format_type == 'csv':
with open(manifest_file, 'w', encoding='utf-8', newline='') as f:
writer = csv.writer(f)
writer.writerow(['类型', '原文件名', '新文件名/错误', '完整路径/原因', '处理时间'])
for item in self.changed_files:
writer.writerow(['成功', item['原文件名'], item['新文件名'],
item['完整路径'], item['处理时间']])
for item in self.failed_files:
writer.writerow(['失败', item['文件名'], '错误', item['错误原因'], ''])
for item in self.skipped_files:
writer.writerow(['跳过', item['原文件'], '跳过', item['原因'], ''])
elif format_type == 'json':
with open(manifest_file, 'w', encoding='utf-8') as f:
json.dump(data, f, ensure_ascii=False, indent=2)
return manifest_file
def print_summary(self):
"""打印处理摘要"""
print("\n" + "=" * 50)
print("处理完成!")
print(f"成功处理:{len(self.changed_files)} 个文件")
print(f"处理失败:{len(self.failed_files)} 个文件")
print(f"跳过文件:{len(self.skipped_files)} 个文件")
if self.failed_files:
print("\n失败文件详情:")
for item in self.failed_files:
print(f" - {item['文件名']}: {item['错误原因']}")
if self.skipped_files:
print("\n跳过文件详情:")
for item in self.skipped_files:
print(f" - {item['原文件']}: {item['原因']}")
def main():
parser = argparse.ArgumentParser(description='批量给文件添加前缀并生成清单')
parser.add_argument('--folder', '-f', type=str, default='.',
help='要处理的文件夹路径(默认当前目录)')
parser.add_argument('--prefix', '-p', type=str, required=True,
help='要添加的前缀')
parser.add_argument('--extensions', '-e', type=str, nargs='+',
help='要处理的文件扩展名(如 .txt .jpg),不指定则处理所有文件')
parser.add_argument('--recursive', '-r', action='store_true',
help='递归处理子文件夹')
parser.add_argument('--format', '-fmt', type=str, choices=['txt', 'csv', 'json'],
default='txt', help='清单格式(默认txt)')
parser.add_argument('--dry-run', action='store_true',
help='预览模式,不实际执行')
args = parser.parse_args()
# 检查文件夹是否存在
if not os.path.exists(args.folder):
print(f"错误:文件夹 {args.folder} 不存在")
sys.exit(1)
if not os.path.isdir(args.folder):
print(f"错误:{args.folder} 不是文件夹")
sys.exit(1)
# 创建管理器
manager = FilePrefixManager(
folder_path=args.folder,
prefix=args.prefix,
extensions=args.extensions,
recursive=args.recursive
)
# 查找文件
all_files = manager.get_all_files()
print(f"找到 {len(all_files)} 个文件待处理")
# 预览模式
if args.dry_run:
print("\n预览模式,实际不会执行:")
for file_path in all_files:
dir_name = os.path.dirname(file_path)
old_name = os.path.basename(file_path)
new_name = args.prefix + old_name
print(f" {old_name} -> {new_name}")
print("\n预览完成,共会修改以上文件")
return
# 确认执行
response = input(f"\n确认给这 {len(all_files)} 个文件添加前缀 '{args.prefix}'?(y/N): ")
if response.lower() != 'y':
print("操作已取消")
return
# 执行处理
manager.process_all_files()
# 生成清单
manifest_file = manager.generate_manifest(args.format)
print(f"\n清单已生成:{manifest_file}")
# 打印摘要
manager.print_summary()
if __name__ == '__main__':
main()
Bash版本(Linux/Mac)
#!/bin/bash
# 批量加前缀脚本
set -e
# 显示使用帮助
usage() {
echo "用法: $0 -p PREFIX [-d DIRECTORY] [-e EXTENSIONS] [-r]"
echo " -p PREFIX 要添加的前缀"
echo " -d DIRECTORY 目标文件夹(默认当前目录)"
echo " -e EXT 文件扩展名,逗号分隔(如 txt,jpg)"
echo " -r 递归处理子文件夹"
echo " -h 显示帮助"
exit 1
}
# 默认值
PREFIX=""
DIRECTORY="."
EXTENSIONS=""
RECURSIVE=false
# 解析参数
while getopts "p:d:e:rh" opt; do
case $opt in
p) PREFIX="$OPTARG" ;;
d) DIRECTORY="$OPTARG" ;;
e) EXTENSIONS="$OPTARG" ;;
r) RECURSIVE=true ;;
h) usage ;;
*) usage ;;
esac
done
# 检查必需参数
if [ -z "$PREFIX" ]; then
echo "错误:必须指定前缀"
usage
fi
# 检查目录
if [ ! -d "$DIRECTORY" ]; then
echo "错误:目录 $DIRECTORY 不存在"
exit 1
fi
echo "开始处理文件夹: $DIRECTORY"
echo "添加前缀: $PREFIX"
# 创建清单文件
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
MANIFEST_FILE="${DIRECTORY}/file_manifest_${TIMESTAMP}.txt"
echo "批量重命名清单" > "$MANIFEST_FILE"
echo "生成时间: $(date '+%Y-%m-%d %H:%M:%S')" >> "$MANIFEST_FILE"
echo "前缀: $PREFIX" >> "$MANIFEST_FILE"
echo "========================================" >> "$MANIFEST_FILE"
# 处理文件函数
process_files() {
local dir="$1"
local file
local success=0
local failed=0
for file in "$dir"/*; do
# 跳过目录
[ -d "$file" ] && continue
# 检查扩展名
if [ -n "$EXTENSIONS" ]; then
ext="${file##*.}"
if [[ ",$EXTENSIONS," != *",$ext,"* ]]; then
continue
fi
fi
old_name=$(basename "$file")
old_path="$dir/$old_name"
new_path="$dir/${PREFIX}${old_name}"
# 检查新文件是否已存在
if [ -e "$new_path" ]; then
echo "跳过: $old_name (目标文件已存在)"
echo "跳过: $old_name" >> "$MANIFEST_FILE"
continue
fi
# 执行重命名
if mv "$old_path" "$new_path" 2>/dev/null; then
echo "成功: $old_name -> ${PREFIX}${old_name}"
echo "成功: $old_name -> ${PREFIX}${old_name}" >> "$MANIFEST_FILE"
((success++))
else
echo "失败: $old_name"
echo "失败: $old_name" >> "$MANIFEST_FILE"
((failed++))
fi
done
return 0
}
# 主处理逻辑
total_success=0
total_failed=0
if [ "$RECURSIVE" = true ]; then
# 递归处理
while IFS= read -r dir; do
echo "处理目录: $dir"
process_files "$dir"
done < <(find "$DIRECTORY" -type d)
else
# 只处理当前目录
process_files "$DIRECTORY"
fi
echo "========================================"
echo "处理完成!"
echo "清单已保存到: $MANIFEST_FILE"
Windows PowerShell版本
# 批量加前缀脚本 (PowerShell)
param(
[Parameter(Mandatory=$true)]
[string]$Prefix,
[string]$Directory = ".",
[string]$Extensions = "",
[switch]$Recursive
)
# 检查目录
if (-not (Test-Path $Directory)) {
Write-Host "错误:目录 $Directory 不存在" -ForegroundColor Red
exit 1
}
# 准备清单对象
$manifest = @()
$successCount = 0
$failedCount = 0
$skipCount = 0
# 获取文件列表
function Get-Files {
param([string]$Path, [string]$Ext, [bool]$Rec)
if ($Rec) {
Get-ChildItem $Path -File -Recurse
} else {
Get-ChildItem $Path -File
}
}
$files = Get-Files -Path $Directory -Ext $Extensions -Rec $Recursive.IsPresent
# 筛选扩展名
if ($Extensions) {
$extList = $Extensions -split ','
$files = $files | Where-Object {
$extList -contains $_.Extension.TrimStart('.')
}
}
Write-Host "找到 $($files.Count) 个文件待处理" -ForegroundColor Yellow
foreach ($file in $files) {
$oldName = $file.Name
$newName = $Prefix + $oldName
$newPath = Join-Path $file.DirectoryName $newName
try {
# 检查目标文件是否已存在
if (Test-Path $newPath) {
Write-Host "跳过: $oldName (目标文件已存在)" -ForegroundColor Gray
$manifest += [PSCustomObject]@{
类型 = '跳过'
原文件名 = $oldName
新文件名 = $newName
完整路径 = $newPath
原因 = '目标文件已存在'
}
$skipCount++
continue
}
# 执行重命名
Rename-Item $file.FullName -NewName $newName -ErrorAction Stop
Write-Host "成功: $oldName -> $newName" -ForegroundColor Green
$manifest += [PSCustomObject]@{
类型 = '成功'
原文件名 = $oldName
新文件名 = $newName
完整路径 = $newPath
原因 = ''
}
$successCount++
} catch {
Write-Host "失败: $oldName - $($_.Exception.Message)" -ForegroundColor Red
$manifest += [PSCustomObject]@{
类型 = '失败'
原文件名 = $oldName
新文件名 = $newName
完整路径 = $newPath
原因 = $_.Exception.Message
}
$failedCount++
}
}
# 生成清单文件
$timestamp = Get-Date -Format 'yyyyMMdd_HHmmss'
$manifestFile = Join-Path $Directory "文件清单_$timestamp.csv"
try {
$manifest | Export-Csv -Path $manifestFile -NoTypeInformation -Encoding UTF8
Write-Host "`n清单已保存到: $manifestFile" -ForegroundColor Cyan
} catch {
Write-Host "清单保存失败: $($_.Exception.Message)" -ForegroundColor Red
}
# 显示统计
Write-Host "`n========== 处理完成 ==========" -ForegroundColor Yellow
Write-Host "成功: $successCount" -ForegroundColor Green
Write-Host "失败: $failedCount" -ForegroundColor Red
Write-Host "跳过: $skipCount" -ForegroundColor Gray
使用方法
Python版本
# 基本用法:给当前目录所有文件加前缀 python file_prefix_manager.py -p "2024_" # 指定文件夹和扩展名 python file_prefix_manager.py -f ./docs -p "backup_2024_" -e .txt .pdf # 递归处理子文件夹 python file_prefix_manager.py -f ./project -p "v2_" -r # 生成JSON格式清单 python file_prefix_manager.py -f ./photos -p "2024_" -fmt json # 预览模式 python file_prefix_manager.py -f . -p "test_" --dry-run
Bash版本
# 使用方法 chmod +x add_prefix.sh ./add_prefix.sh -p "2024_" -d ./docs ./add_prefix.sh -p "IMG_" -d ./photos -e jpg,png -r
PowerShell版本
.\add_prefix.ps1 -Prefix "2024_" -Directory "D:\docs" .\add_prefix.ps1 -Prefix "IMG_" -Directory "D:\photos" -Extensions "jpg,png" -Recursive
功能特点
- 多种格式清单:txt、CSV、JSON
- 扩展名筛选:可指定处理特定类型的文件
- 递归处理:可处理子文件夹
- 安全预览:先预览再执行
- 错误处理:跳过已存在文件,记录失败原因
- 统计信息:成功、失败、跳过统计
选择适合你系统环境的脚本使用即可!