批量加前缀并创建清单的脚本

wen 实用脚本 2

本文目录导读:

批量加前缀并创建清单的脚本

  1. Python版本(推荐)
  2. Bash版本(Linux/Mac)
  3. Windows PowerShell版本
  4. 使用方法
  5. 功能特点

我来为你编写一个批量给文件加前缀并创建清单的脚本。

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

功能特点

  1. 多种格式清单:txt、CSV、JSON
  2. 扩展名筛选:可指定处理特定类型的文件
  3. 递归处理:可处理子文件夹
  4. 安全预览:先预览再执行
  5. 错误处理:跳过已存在文件,记录失败原因
  6. 统计信息:成功、失败、跳过统计

选择适合你系统环境的脚本使用即可!

抱歉,评论功能暂时关闭!