批量重命名脚本#

脚本说明#

批量重命名脚本用于批量重命名文件,支持多种重命名模式,包括添加前缀、后缀、替换文本、大小写转换等。

脚本代码#

#!/bin/bash

# 批量重命名脚本
# 功能:批量重命名文件,支持多种重命名模式
# 作者:System Admin
# 日期:2026-01-01

set -euo pipefail

# 配置变量
DRY_RUN=false
VERBOSE=false
RECURSIVE=false
PATTERN="*"
MODE="prefix"

# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
BLUE='\033[0;34m'
NC='\033[0m'

# 日志函数
log() {
    local level=$1
    shift
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
    echo "[$timestamp] [$level] $@"
}

log_info() {
    log "INFO" "$@"
}

log_error() {
    log "ERROR" "$@"
}

log_warning() {
    log "WARNING" "$@"
}

# 添加前缀
add_prefix() {
    local prefix=$1
    local files=($2)
    
    log_info "添加前缀: $prefix"
    
    for file in "${files[@]}"; do
        if [ -f "$file" ]; then
            local new_name="${prefix}${file}"
            
            if [ "$DRY_RUN" = true ]; then
                echo -e "${BLUE}[DRY RUN]${NC} 重命名: $file -> $new_name"
            else
                if mv "$file" "$new_name"; then
                    echo -e "${GREEN}[SUCCESS]${NC} 重命名: $file -> $new_name"
                else
                    echo -e "${RED}[ERROR]${NC} 重命名失败: $file"
                fi
            fi
        fi
    done
}

# 添加后缀
add_suffix() {
    local suffix=$1
    local files=($2)
    
    log_info "添加后缀: $suffix"
    
    for file in "${files[@]}"; do
        if [ -f "$file" ]; then
            local extension="${file##*.}"
            local basename="${file%.*}"
            
            if [ "$basename" = "$file" ]; then
                local new_name="${file}${suffix}"
            else
                local new_name="${basename}${suffix}.${extension}"
            fi
            
            if [ "$DRY_RUN" = true ]; then
                echo -e "${BLUE}[DRY RUN]${NC} 重命名: $file -> $new_name"
            else
                if mv "$file" "$new_name"; then
                    echo -e "${GREEN}[SUCCESS]${NC} 重命名: $file -> $new_name"
                else
                    echo -e "${RED}[ERROR]${NC} 重命名失败: $file"
                fi
            fi
        fi
    done
}

# 替换文本
replace_text() {
    local old_text=$1
    local new_text=$2
    local files=($3)
    
    log_info "替换文本: '$old_text' -> '$new_text'"
    
    for file in "${files[@]}"; do
        if [ -f "$file" ]; then
            local new_name="${file//$old_text/$new_text}"
            
            if [ "$new_name" != "$file" ]; then
                if [ "$DRY_RUN" = true ]; then
                    echo -e "${BLUE}[DRY RUN]${NC} 重命名: $file -> $new_name"
                else
                    if mv "$file" "$new_name"; then
                        echo -e "${GREEN}[SUCCESS]${NC} 重命名: $file -> $new_name"
                    else
                        echo -e "${RED}[ERROR]${NC} 重命名失败: $file"
                    fi
                fi
            fi
        fi
    done
}

# 大小写转换
convert_case() {
    local case_type=$1
    local files=($2)
    
    log_info "大小写转换: $case_type"
    
    for file in "${files[@]}"; do
        if [ -f "$file" ]; then
            local new_name
            
            case $case_type in
                upper)
                    new_name=$(echo "$file" | tr '[:lower:]' '[:upper:]')
                    ;;
                lower)
                    new_name=$(echo "$file" | tr '[:upper:]' '[:lower:]')
                    ;;
                title)
                    new_name=$(echo "$file" | sed 's/\b\(\w\)/\U\1/g')
                    ;;
                *)
                    log_error "无效的大小写转换类型: $case_type"
                    return 1
                    ;;
            esac
            
            if [ "$new_name" != "$file" ]; then
                if [ "$DRY_RUN" = true ]; then
                    echo -e "${BLUE}[DRY RUN]${NC} 重命名: $file -> $new_name"
                else
                    if mv "$file" "$new_name"; then
                        echo -e "${GREEN}[SUCCESS]${NC} 重命名: $file -> $new_name"
                    else
                        echo -e "${RED}[ERROR]${NC} 重命名失败: $file"
                    fi
                fi
            fi
        fi
    done
}

# 序列重命名
sequence_rename() {
    local prefix=$1
    local start_num=$2
    local files=($3)
    
    log_info "序列重命名: $prefix, 起始数字: $start_num"
    
    local num=$start_num
    for file in "${files[@]}"; do
        if [ -f "$file" ]; then
            local extension="${file##*.}"
            local new_name="${prefix}${num}.${extension}"
            
            if [ "$DRY_RUN" = true ]; then
                echo -e "${BLUE}[DRY RUN]${NC} 重命名: $file -> $new_name"
            else
                if mv "$file" "$new_name"; then
                    echo -e "${GREEN}[SUCCESS]${NC} 重命名: $file -> $new_name"
                else
                    echo -e "${RED}[ERROR]${NC} 重命名失败: $file"
                fi
            fi
            
            num=$((num + 1))
        fi
    done
}

# 按日期重命名
date_rename() {
    local date_format=$1
    local files=($2)
    
    log_info "按日期重命名: $date_format"
    
    for file in "${files[@]}"; do
        if [ -f "$file" ]; then
            local date_str=$(date +"$date_format")
            local extension="${file##*.}"
            local new_name="${date_str}.${extension}"
            
            if [ "$DRY_RUN" = true ]; then
                echo -e "${BLUE}[DRY RUN]${NC} 重命名: $file -> $new_name"
            else
                if mv "$file" "$new_name"; then
                    echo -e "${GREEN}[SUCCESS]${NC} 重命名: $file -> $new_name"
                else
                    echo -e "${RED}[ERROR]${NC} 重命名失败: $file"
                fi
            fi
        fi
    done
}

# 显示帮助
show_help() {
    echo "用法: $0 [选项] <模式> [参数]"
    echo ""
    echo "选项:"
    echo "  -d        试运行模式(不实际重命名)"
    echo "  -v        详细输出"
    echo "  -r        递归处理子目录"
    echo "  -p <pattern>  文件模式(默认: *)"
    echo "  -h        显示帮助信息"
    echo ""
    echo "模式:"
    echo "  prefix <前缀>              添加前缀"
    echo "  suffix <后缀>              添加后缀"
    echo "  replace <旧文本> <新文本>  替换文本"
    echo "  upper                      转换为大写"
    echo "  lower                      转换为小写"
    echo "  title                      转换为标题格式"
    echo "  sequence <前缀> <起始数字>  序列重命名"
    echo "  date <日期格式>            按日期重命名"
    echo ""
    echo "示例:"
    echo "  $0 prefix \"backup_\" *.txt"
    echo "  $0 suffix \"_old\" *.jpg"
    echo "  $0 replace \"old\" \"new\" *.txt"
    echo "  $0 lower *.TXT"
    echo "  $0 sequence \"photo_\" 1 *.jpg"
    echo "  $0 date \"%Y%m%d\" *.jpg"
}

# 主函数
main() {
    # 解析选项
    while getopts "dvrp:h" opt; do
        case $opt in
            d)
                DRY_RUN=true
                log_info "启用试运行模式"
                ;;
            v)
                VERBOSE=true
                log_info "启用详细输出"
                ;;
            r)
                RECURSIVE=true
                log_info "启用递归处理"
                ;;
            p)
                PATTERN="$OPTARG"
                log_info "文件模式: $PATTERN"
                ;;
            h)
                show_help
                exit 0
                ;;
            *)
                log_error "无效选项: $opt"
                show_help
                exit 1
                ;;
        esac
    done
    
    shift $((OPTIND - 1))
    
    # 检查参数
    if [ $# -eq 0 ]; then
        log_error "缺少模式参数"
        show_help
        exit 1
    fi
    
    MODE=$1
    shift
    
    # 获取文件列表
    local files=()
    if [ "$RECURSIVE" = true ]; then
        while IFS= read -r -d '' file; do
            files+=("$file")
        done < <(find . -type f -name "$PATTERN" -print0)
    else
        files=($PATTERN)
    fi
    
    # 检查文件列表
    if [ ${#files[@]} -eq 0 ]; then
        log_error "没有找到匹配的文件: $PATTERN"
        exit 1
    fi
    
    log_info "找到 ${#files[@]} 个文件"
    
    # 根据模式执行重命名
    case $MODE in
        prefix)
            if [ $# -eq 0 ]; then
                log_error "缺少前缀参数"
                exit 1
            fi
            add_prefix "$1" "${files[@]}"
            ;;
        suffix)
            if [ $# -eq 0 ]; then
                log_error "缺少后缀参数"
                exit 1
            fi
            add_suffix "$1" "${files[@]}"
            ;;
        replace)
            if [ $# -lt 2 ]; then
                log_error "缺少替换文本参数"
                exit 1
            fi
            replace_text "$1" "$2" "${files[@]}"
            ;;
        upper)
            convert_case "upper" "${files[@]}"
            ;;
        lower)
            convert_case "lower" "${files[@]}"
            ;;
        title)
            convert_case "title" "${files[@]}"
            ;;
        sequence)
            if [ $# -lt 2 ]; then
                log_error "缺少序列重命名参数"
                exit 1
            fi
            sequence_rename "$1" "$2" "${files[@]}"
            ;;
        date)
            if [ $# -eq 0 ]; then
                log_error "缺少日期格式参数"
                exit 1
            fi
            date_rename "$1" "${files[@]}"
            ;;
        *)
            log_error "无效的模式: $MODE"
            show_help
            exit 1
            ;;
    esac
    
    if [ "$DRY_RUN" = true ]; then
        log_info "试运行模式完成,未实际重命名文件"
    else
        log_info "重命名完成"
    fi
}

# 执行主函数
main "$@"

使用说明#

  1. 添加执行权限:

    chmod +x batch_rename.sh
  2. 基本用法:

    # 添加前缀
    ./batch_rename.sh prefix "backup_" *.txt
    
    # 添加后缀
    ./batch_rename.sh suffix "_old" *.jpg
    
    # 替换文本
    ./batch_rename.sh replace "old" "new" *.txt
    
    # 转换为小写
    ./batch_rename.sh lower *.TXT
    
    # 序列重命名
    ./batch_rename.sh sequence "photo_" 1 *.jpg
    
    # 按日期重命名
    ./batch_rename.sh date "%Y%m%d" *.jpg
  3. 高级选项:

    # 试运行模式(不实际重命名)
    ./batch_rename.sh -d prefix "backup_" *.txt
    
    # 递归处理子目录
    ./batch_rename.sh -r lower *.TXT
    
    # 指定文件模式
    ./batch_rename.sh -p "*.log" suffix "_archived"
    
    # 详细输出
    ./batch_rename.sh -v replace "temp" "backup" *.txt

功能特点#

  • 支持多种重命名模式
  • 添加前缀/后缀
  • 文本替换
  • 大小写转换
  • 序列重命名
  • 按日期重命名
  • 递归处理子目录
  • 试运行模式
  • 详细的操作日志

注意事项#

  1. 建议先使用试运行模式(-d选项)查看将要执行的操作
  2. 重命名前备份重要文件
  3. 注意文件名中的特殊字符
  4. 确保目标文件名不会冲突
  5. 递归处理时注意目录结构