面對成百上千檔案需重新命名,手動操作不現實。本文介紹 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
#!/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
確認版本:rename --version 輸出含 File::Rename 或 Perl 字樣即為 Perl 版。
| 需求 | 指令 | 說明 |
|---|---|---|
| 移除檔名空格 | rename 's/ /_/g' * | 空格→底線 |
| 大寫轉小寫 | rename 'y/A-Z/a-z/' * | 字元轉換 |
| 擴展名 .jpeg→.jpg | rename 's/\.jpeg$/.jpg/i' * | 忽略大小寫 |
| 前綴添加 | rename 's/^/prefix_/' * | 開頭加字串 |
| 後綴添加 | rename 's/$/.bak/' * | 結尾加字串 |
| 移除 .bak 後綴 | rename 's/\.bak$//' * | 結尾刪除 |
| 序號補零 1.jpg→001.jpg | rename 's/^(\d+)\.jpg$/sprintf("%03d.jpg",$1)/e' *.jpg | Perl 表達式評估 |
| 日期格式 2024.01.15→20240115 | rename 's/(\d{4})\.(\d{2})\.(\d{2})/$1$2$3/' * | 捕獲群組重組 |
for dir in */; do
(cd "$dir" && rename "s/^/${dir%/}_/" *.jpg)
done
# 避免 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{}:佔位符替換
# 安裝: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"
#!/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)。
rename -n 's/.../' * (-n 乾跑模式)cp -r dir dir.bak 或 git init && git add -A && git commit -m "before rename"mv -n、rename -nrename -v 's/.../' * > rename_log.txt
需求複雜度
│
├─ 簡單模式替換(前綴、後綴、大小寫、空格) → rename (Perl) 一行指令
│
├─ 需邏輯判斷(計數、條件、多步驟) → Bash/Python 腳本
│
├─ 超大量檔案(10萬+) → find + xargs -P 並行
│
├─ 結構化模式(通配符對應) → mmv
│
└─ 依賴檔案元數據(EXIF、ID3、文件屬性) → exiftool + 腳本 / Python
批量重命名核心是模式識別與轉換邏輯。Perl rename 以正則表達式處理最靈活;Bash 腳本適合複雜邏輯與元數據結合;find + xargs 解決參數列表過長與並行加速。務必養成乾跑驗證、備份原檔、記錄日誌三步驟,讓大規模重命名安全可控。