自从多年前放弃Windows,完全改用Linux作为日常工作环境后,遇到的其中一个麻烦,就是解压缩来自Windows系统的zip压缩包,一旦涉及文件名或目录名有中文,其解压缩结果就总是乱码。之前尝试过各种环境变量配置方法和第三方工具,但都没法很好地解决,于是只好请同事朋友改用rar格式压缩,或者干脆弄个Windows虚拟机,回到Windows系统中解压缩。

最近通过一系列调研和尝试,终于找到了合适的解决方法,大致需要考虑两个方面:

  1. 在运行unzip命令时,需要指定字符集为zh_CN.GBK,且同时带上-UU参数,以确保unzip结果不会根据缺省字符集utf8进行转码;
  2. 然后,需要遍历解压缩的整个目录树,使用convmv -f gbk -t utf8命令进行改名,将字符集从gbk转换到utf8。

在使用convmv改名前,应先对其中各目录设置可写权限,否则该目录下的文件改名会因权限问题而失败。

整个过程,我写了一个简单的小脚本unzipw.sh,内容如下:

sh
 1#!/bin/bash
 2
 3if [ -z "$1" ]; then
 4    echo "Extract .zip file from Windows."
 5    echo "Usage: $(basename $0) <xx.zip>"
 6    exit 1
 7fi
 8
 9DIRNAME="$(basename "$1" .zip)"
10if [ -d "${DIRNAME}" ]; then
11    DIRNAME="$(mktemp -d "${DIRNAME}-XXXX")"
12fi
13mkdir -pv "${DIRNAME}"
14
15set -e
16
17# extract files
18LANG=zh_CN.GBK unzip -UU "$1" -d "${DIRNAME}"
19
20# allow to modify directory
21find "${DIRNAME}" -type d -exec chmod u+w "{}" \;
22
23# correct encoding
24convmv -f gbk -t utf8 --notest -r "${DIRNAME}"
25
26# move single subdir out
27if [ "$(ls "${DIRNAME}")" == "${DIRNAME}" ]; then
28    mv "${DIRNAME}/${DIRNAME}"/* "${DIRNAME}/"
29    rmdir "${DIRNAME}/${DIRNAME}"
30fi

从此,对来自Windows系统的zip压缩包,处理起来就很方便了。