萬盛學電腦網

您现在的位置: 萬盛學電腦網 >> 作業系統 >  >> Linux 教學

Linux 批量重命名檔案實戰:Shell 腳本與 rename 指令高效技巧

面對成百上千檔案需重新命名,手動操作不現實。本文介紹 Shell 迴圈、rename (Perl 版)、mmv、find + xargs 等多種批量重命名方案,並針對日期正規化、序號補零、擴展名統一、特殊字元清理等常見場景提供現成腳本。

場景分析:目錄結構與命名目標

# 現狀
10.11/
  IMG_001.jpg
  IMG_002.jpg
10.12/
  photo.jpg
  snap.png

# 目標:以父目錄名稱重命名
10.11/
  1011.jpg
  1011_002.jpg
10.12/
  1012.jpg
  1012_002.jpg

方案一:Bash 迴圈(零依賴、普遍相容)

#!/bin/bash
# rename_by_dir.sh - 以父目錄名重命名圖片

for dir in */; do
    [[ -d "$dir" ]] || continue
    dirname="${dir%/}"           # 移除尾部斜線
    newbase="${dirname//./}"     # 移除點號:10.11 → 1011
    
    cd "$dir" || continue
    count=0
    for file in *.jpg *.jpeg *.png *.JPG *.JPEG *.PNG; do
        [[ -f "$file" ]] || continue
        ((count++))
        ext="${file##*.}"
        # 格式:1011.jpg, 1011_002.jpg, 1011_003.jpg...
        if ((count == 1)); then
            newname="${newbase}.${ext}"
        else
            newname="${newbase}_$(printf '%03d' $count).${ext}"
        fi
        mv -n "$file" "$newname"  # -n 不覆蓋
        echo "Renamed: $file → $newname"
    done
    cd ..
done

方案二:Perl rename(正則表達式強大、一行搞定)

確認版本:rename --version 輸出含 File::Rename 或 Perl 字樣即為 Perl 版。

常用單行指令

需求指令說明
移除檔名空格rename 's/ /_/g' *空格→底線
大寫轉小寫rename 'y/A-Z/a-z/' *字元轉換
擴展名 .jpeg→.jpgrename 's/\.jpeg$/.jpg/i' *忽略大小寫
前綴添加rename 's/^/prefix_/' *開頭加字串
後綴添加rename 's/$/.bak/' *結尾加字串
移除 .bak 後綴rename 's/\.bak$//' *結尾刪除
序號補零 1.jpg→001.jpgrename 's/^(\d+)\.jpg$/sprintf("%03d.jpg",$1)/e' *.jpgPerl 表達式評估
日期格式 2024.01.15→20240115rename 's/(\d{4})\.(\d{2})\.(\d{2})/$1$2$3/' *捕獲群組重組

實戰:目錄名作為前綴


for dir in */; do
    (cd "$dir" && rename "s/^/${dir%/}_/" *.jpg)
done

方案三:find + xargs 並行處理大量檔案


# 避免 Argument list too long
find . -type f -name '*.jpg' -print0 | 
xargs -0 -P4 -I{} bash -c '
    f="{}"
    dir=$(basename "$(dirname "$f")")
    base=$(basename "$f")
    new="${dir//./}_${base}"
    mv -n "$f" "$(dirname "$f")/$new"
'
  • -print0/-0:處理含空格/特殊字元檔名
  • -P4:4 進程並行
  • -I{}:佔位符替換

方案四:mmv(標準移動重命名工具)


# 安裝:apt/yum install mmv
# 模式:mmv "來源模式" "目標模式"
# #1, #2 對應通配符捕獲群組

# 例:IMG_001.jpg → 001_IMG.jpg
mmv "IMG_*.jpg" "#1#2_IMG.jpg"

# 例:a_b_c.txt → a-b-c.txt
mmv "*_*_*" "#1-#2-#3"

進階場景:EXIF 日期重命名(照片整理神技)


#!/bin/bash
# exif_rename.sh - 依拍攝日期重命名:20240115_143022.jpg

for f in *.jpg *.JPG; do
    [[ -f "$f" ]] || continue
    # 讀取 EXIF DateTimeOriginal
    dt=$(exiftool -DateTimeOriginal -s3 -d "%Y%m%d_%H%M%S" "$f" 2>/dev/null)
    if [[ -n "$dt" ]]; then
        ext="${f##*.}"
        new="${dt}.${ext}"
        # 避免同秒多張衝突
        i=1
        while [[ -e "$new" ]]; do
            new="${dt}_$(printf '%03d' $i).${ext}"
            ((i++))
        done
        mv -n "$f" "$new"
        echo "$f → $new"
    fi
done

需安裝 exiftool (perl-Image-ExifTool)。

安全最佳實踐

  1. 先試跑:rename -n 's/.../' * (-n 乾跑模式)
  2. 備份原檔:cp -r dir dir.bak 或 git init && git add -A && git commit -m "before rename"
  3. 不覆蓋:mv -n、rename -n
  4. 記錄對應表:rename -v 's/.../' * > rename_log.txt
  5. 分批驗證:先處理子目錄確認無誤再全量執行

工具選擇決策樹


需求複雜度
    │
    ├─ 簡單模式替換(前綴、後綴、大小寫、空格) → rename (Perl) 一行指令
    │
    ├─ 需邏輯判斷(計數、條件、多步驟) → Bash/Python 腳本
    │
    ├─ 超大量檔案(10萬+) → find + xargs -P 並行
    │
    ├─ 結構化模式(通配符對應) → mmv
    │
    └─ 依賴檔案元數據(EXIF、ID3、文件屬性) → exiftool + 腳本 / Python

小結

批量重命名核心是模式識別與轉換邏輯。Perl rename 以正則表達式處理最靈活;Bash 腳本適合複雜邏輯與元數據結合;find + xargs 解決參數列表過長與並行加速。務必養成乾跑驗證、備份原檔、記錄日誌三步驟,讓大規模重命名安全可控。

copyright © 萬盛學電腦網 all rights reserved