Windows XP Windows 7 Windows 2003 Windows Vista Windows 綜合教學 Linux 系統教學
Windows 10 Windows 8 Windows 2008 Windows NT Windows Server 電腦軟體教學
您现在的位置: Windows教程網 >> Windows教程 >  >> Linux 系統教學 >> Linux 教學

Linux 檔案名亂碼批次轉碼實戰:convmv 從 GBK/Big5 遷移至 UTF-8 完整指南

編輯:Linux 教學

跨平台檔案傳輸 (Linux ↔ Windows、macOS、Samba、FTP、雲端同步) 最常遇到的問題是檔案名編碼不一致:Windows 歷史使用 GBK/CP936、繁中環境用 Big5/CP950,Linux 現代預設 UTF-8。直接複製會導致中文檔名變成亂碼或問號。本文詳細說明 convmv 批次轉碼全流程、編碼偵測技巧、特殊字符處理、Samba/NFS 伺服器端預轉碼配置與驗證腳本。

核心工具:convmv


# 安裝
# Debian/Ubuntu
apt install -y convmv
# RHEL/CentOS/Rocky
dnf install -y convmv
# Arch/Manjaro
pacman -S convmv
# macOS (Homebrew)
brew install convmv

基本語法與常用參數


convmv -f <來源編碼> -t <目標編碼> [選項] <檔案/目錄>

常用參數:
  -r, --recursive          遞迴處理子目錄
  --notest                 實際執行重命名 (預設僅模擬顯示)
  --list                   列出所有支援編碼
  --unescap                處理 URL 編碼 (如 %20 → 空格)
  --replace                替換無法轉換字符為 _
  --lower / --upper        檔案名轉大小寫
  -q, --quiet              僅顯示錯誤
  -v, --verbose            詳細輸出

編碼偵測:確認來源編碼的三種方法

  1. 檔案系統層級:ls -la 觀察亂碼模式
    • GBK → 顯示為多個拉丁字符 (如 極ç)
    • Big5 → 顯示為 ?? 或部分字符缺失
    • UTF-8 已正確 → 正常顯示中文
  2. Python 快速偵測腳本:
    
    python3 -c "
    import os, sys
    for name in os.listdir('.'):
        try:
            name.encode('utf-8').decode('utf-8')
            print(f'UTF-8 OK: {name}')
        except UnicodeError:
            for enc in ['gbk', 'gb18030', 'big5', 'cp950']:
                try:
                    decoded = name.encode('latin-1').decode(enc)
                    print(f'{enc.upper()}: {name} → {decoded}')
                    break
                except:
                    pass
    "
    
  3. file 指令 (針對檔案內容,非檔名):file -i filename 參考用

實戰轉碼流程

場景 A:Linux 本地目錄 GBK → UTF-8


# 1. 先模擬預覽 (無 --notest)
convmv -f gbk -t utf-8 -r /path/to/dir

# 2. 確認無誤後實際執行
convmv -f gbk -t utf-8 -r --notest /path/to/dir

# 3. 驗證
ls -la /path/to/dir

場景 B:Samba 共享 Windows 建立的 GBK 檔名


# Samba 伺服器端配置 /etc/samba/smb.conf
[global]
    unix charset = UTF-8
    dos charset = CP936
    # 讓 Samba 自動在 UTF-8 ↔ CP936 間轉換檔案名
    # 客戶端 (Windows) 看到正常中文,Linux 底層儲存為 UTF-8

若歷史遺留檔名已為亂碼,需在 Linux 端離線執行 convmv 修復。

場景 C:壓縮檔內部檔名編碼修復


# 1. 解壓至暫存目錄
mkdir /tmp/extract && cd /tmp/extract
unzip ../archive.zip   # 或 tar xf, 7z x

# 2. 轉碼檔名
convmv -f gbk -t utf-8 -r --notest .

# 3. 重新打包
cd .. && zip -r archive_fixed.zip extract/

特殊字符與邊界情況處理

情況現象解決方案
檔名含不可轉換字符convmv 報錯 Skipping, unable to convert加 --replace 替換為 _,或手動重命名
檔名含換行符/控制字符Shell 處理困難find . -depth -execdir convmv -f gbk -t utf-8 --notest {} +
同目錄轉碼後檔名衝突File exists 錯誤先 convmv --lower 統一小寫,或腳本偵測衝突加後綴
符號連結目標路徑編碼連結指向錯誤find -type l -exec sh -c 'ln -sf "$(readlink {} | iconv -f gbk -t utf-8)" {}' \;

批次驗證腳本:確保零遺漏、零衝突


#!/bin/bash
# verify_utf8_filenames.sh
set -euo pipefail
TARGET_DIR="${1:-.}"

echo "=== 掃描非 UTF-8 檔名 ==="
find "$TARGET_DIR" -depth -print0 | while IFS= read -r -d '' file; do
    name=$(basename "$file")
    if ! printf '%s' "$name" | iconv -f utf-8 -t utf-8 >/dev/null 2>&1; then
        echo "非 UTF-8: $file"
    fi
done

echo "=== 檢查重複檔名 (不區分大小寫) ==="
find "$TARGET_DIR" -type f -printf "%f\n" | tr '[:upper:]' '[:lower:]' | sort | uniq -d

echo "=== 完成 ==="

自動化編碼遷移最佳實踐

  1. 來源端預防:Windows 10 1803+ 可在「地區設定 → 管理語言 → 變更系統地區設定」勾選 Beta: 使用 Unicode UTF-8 提供全球語言支援,使預設編碼為 UTF-8。
  2. 傳輸協定層面:使用支援 UTF-8 的協定 (SFTP/SCP/rsync -z、SMB 3.1.1、WebDAV、REST API),避免 FTP (預設 Latin-1) 與舊版 SMB/CIFS。
  3. 檔案系統層面:ZFS/Btrfs/ext4/xfs 均原生支援 UTF-8 檔名,無需額外配置。
  4. CI/CD 整合:在建構流程中加入 convmv 檢查步驟,阻擋非 UTF-8 檔名進入製品。

建立「編碼偵測 → 模擬預覽 → 實際轉碼 → 驗證零衝突」標準化流程,並從來源端 (Windows 設定)、傳輸層 (協定選擇)、儲存層 (檔案系統)、應用層 (CI/CD 守門) 全鏈路治理,即可徹底消除 Linux 環境下的中文檔名亂碼困擾。

Copyright © Windows教程網 All Rights Reserved