歷史項目遷移、跨平台協作、舊系統數據導入常面臨 GBK/Big5/EUC-JP 到 UTF-8 的編碼轉換需求。本文提供基於 iconv 的遞歸 Shell 腳本,並對比 convmv、enca、Python chardet 等現代工具鏈。

batch_convert.sh#!/bin/bash
# 批量轉換指定目錄下所有文件編碼
# 用法: ./batch_convert.sh 源目錄 目標目錄 源編碼 目標編碼
# 示例: ./batch_convert.sh ./src ./dist GBK UTF-8
set -euo pipefail
SRC_DIR="${1:-.}"
DST_DIR="${2:-./converted}"
FROM_ENC="${3:-GBK}"
TO_ENC="${4:-UTF-8}"
mkdir -p "$DST_DIR"
# 遞歸查找文件(排除二進制、.git、構建產物)
find "$SRC_DIR" -type f \
! -path "*/.git/*" \
! -path "*/node_modules/*" \
! -path "*/__pycache__/*" \
! -name "*.pyc" \
! -name "*.class" \
! -name "*.o" \
! -name "*.so" \
-print0 | while IFS= read -r -d '' file; do
# 計算相對路徑並創建目標目錄
rel_path="${file#$SRC_DIR/}"
dst_file="$DST_DIR/$rel_path"
mkdir -p "$(dirname "$dst_file")"
# 檢測是否為文本文件(跳過二進制)
if file -b "$file" | grep -q "text"; then
echo "Converting: $file -> $dst_file"
iconv -f "$FROM_ENC" -t "$TO_ENC" -c "$file" > "$dst_file" 2>/dev/null || {
echo "WARN: Failed to convert $file (maybe already $TO_ENC or binary)"
cp "$file" "$dst_file"
}
else
echo "Skipping binary: $file"
cp "$file" "$dst_file"
fi
done
echo "Conversion completed. Output: $DST_DIR"
| 參數 | 說明 | 常用值 |
|---|---|---|
-f | 源編碼 | GBK、GB2312、BIG5、EUC-JP、ISO-8859-1、CP936 |
-t | 目標編碼 | UTF-8、UTF-16LE |
-c | 忽略無法轉換字符(防止中斷) | 生產環境必加 |
//TRANSLIT | 近似轉換(如無法轉換用相似字符) | -t UTF-8//TRANSLIT |
//IGNORE | 直接丟棄無法轉換字節 | -t UTF-8//IGNORE |
#!/usr/bin/env python3
# auto_convert.py: 自動檢測編碼並轉 UTF-8
import os, sys, chardet
def convert_file(filepath, target_enc='UTF-8'):
with open(filepath, 'rb') as f:
raw = f.read(10000) # 采樣檢測
result = chardet.detect(raw)
src_enc = result['encoding']
confidence = result['confidence']
if not src_enc or confidence < 0.7:
print(f"SKIP (low confidence): {filepath} -> {src_enc} ({confidence})")
return
if src_enc.lower() == target_enc.lower():
print(f"SKIP (already {target_enc}): {filepath}")
return
try:
content = raw.decode(src_enc)
# 讀取完整文件(大文件需分塊)
with open(filepath, 'r', encoding=src_enc) as f:
full = f.read()
with open(filepath + '.utf8', 'w', encoding=target_enc) as f:
f.write(full)
print(f"CONVERTED: {filepath} ({src_enc} -> {target_enc})")
except Exception as e:
print(f"ERROR: {filepath} - {e}")
if __name__ == '__main__':
root = sys.argv[1] if len(sys.argv) > 1 else '.'
for dirpath, _, filenames in os.walk(root):
for f in filenames:
if f.endswith(('.txt', '.csv', '.sql', '.java', '.cpp', '.h', '.py', '.js', '.html', '.css')):
convert_file(os.path.join(dirpath, f))
# 安裝
yum install convmv -y # 或 apt install convmv
# 預覽(不實際修改)
convmv -f GBK -t UTF-8 -r /path/to/dir --notest
# 實際執行
convmv -f GBK -t UTF-8 -r /path/to/dir
| 需求 | 推薦工具 | 理由 |
|---|---|---|
| 已知源編碼、批量文本轉換 | iconv + find/xargs | 標準、高效、可控 |
| 未知源編碼、需自動檢測 | Python chardet / enca | 智能檢測、可整合腳本 |
| 文件名亂碼修復 | convmv | 專門處理文件名編碼 |
| 大文件(>1GB)流式轉換 | iconv 管道 / Python 分塊讀寫 | 避免記憶體溢出 |
| CI/CD 流水線集成 | iconv (標準庫) / Docker 映像預裝 | 無外部依賴、跨平台 |
編碼轉換的核心是 「檢測 → 驗證 → 轉換 → 校驗」 閉環。iconv 仍是批量文本轉換的基石,**加上 -c 忽略錯誤、//TRANSLIT 近似轉換、二進制文件跳過** 三大防護,配合 chardet 自動檢測未知編碼,可構建健壯的編碼遷移流水線。記住:轉換前務必備份,轉換後抽樣驗證。
Linux rz/sz 文件傳輸實戰:SecureCRT/Xshell 配置與最佳實踐
locate 指令快速定位檔案:資料庫原理、updatedb 更新、參數詳解、與 find 差異比較
Linux 備份 ifcfg-eth0 導致網卡無法綁定 IP?Oracle Linux 5.7 實戰排查
Linux 手動關閉/開啟防火牆:iptables/service/chkconfig/systemd/Ubuntu 專用指令全覽
CentOS 6.5 安裝無線網卡驅動 (Realtek RTL8188CE) 完整編譯教學
Ubuntu 安裝 Visual Studio Code 完整指南:Ubuntu Make 命令列安裝、官方 .deb 套件與 Flatpak/Snap 多種方式比較