本文目录导读:

我来为你编写一个批量给文件加前缀并创建清单的脚本。
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
- 扩展名筛选:可指定处理特定类型的文件
- 递归处理:可处理子文件夹
- 安全预览:先预览再执行
- 错误处理:跳过已存在文件,记录失败原因
- 统计信息:成功、失败、跳过统计
选择适合你系统环境的脚本使用即可!
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播