当前位置: > Linux故障 >

Linux 下 zip 文件解压乱码如何解决?

时间:2016-05-26 01:27来源:linux.it.net.cn 作者:IT
我在ubuntu 10.04下使用unzip,7z,7za都无法正常解压来自windows的文件。带有中文名称的文件夹仍然乱码,请问有什么解决办法



作者:Latm Ake
链接:http://www.zhihu.com/question/20523036/answer/35225920
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

由于zip格式中并没有指定编码格式,Windows下生成的zip文件中的编码是GBK/GB2312等,因此,导致这些zip文件在Linux下解压时出现乱码问题,因为Linux下的默认编码是UTF8。

目前网上流传一种unzip -O cp936的方法,但一些unzip是没有-O这个选项的。

我使用的版本 unzip 6.0 debian modified 版本有这个选项

我发现另外两种解决方案可用。

python方案

此方案目前来看非常完美。


#!/usr/bin/env python
# -*- coding: utf-8 -*-

import os
import sys
import zipfile

#print "Processing File " + sys.argv[1]

file=zipfile.ZipFile(sys.argv[1],"r");
for name in file.namelist():
    utf8name=name.decode('gbk')
#    print "Extracting " + utf8name
    pathname = os.path.dirname(utf8name)
    if not os.path.exists(pathname) and pathname!= "":
        os.makedirs(pathname)
    data = file.read(name)
    if not os.path.exists(utf8name):
        fo = open(utf8name, "w")
        fo.write(data)
        fo.close
file.close()

Windows 用户屏蔽两条 print 语句,Linux 用户不用屏蔽


7z方案

需要安装p7zip和convmv,在Fedora下的命令是


su -c 'yum install p7zip convmv'

在ubuntu下的安装命令是


sudo apt-get install p7zip convmv

安装完之后,就可以用7za和convmv两个命令完成解压缩任务。


LANG=C 7za x your-zip-file.zip
convmv -f GBK -t utf8 --notest -r .

第一条命令用于解压缩,而LANG=C表示以US-ASCII这样的编码输出文件名,如果没有这个语言设置,它同样会输出乱码,只不过是UTF8格式的乱码(convmv会忽略这样的乱码)。

第二条命令是将GBK编码的文件名转化为UTF8编码,-r表示递归访问目录,即对当前目录中所有文件进行转换。




 


本质问题还是zip格式的缺陷,没有字段标志出文件名的编码格式。
ZIP在压缩与解压缩的时候默认使用了系统的本地编码,如windows中文环境下为GBK,日文环境下是JIS,linux默认编码为UTF8等;那么在不同系统环境下,只要压缩与解压缩的编码不一致,就会出现乱码。

一楼提供的python解决方案,最好不要用,简单的处理会有很多风险,比如zip炸弹,目录覆盖,执行病毒文件等。
正确的做法是:尽可能的只使用英文名,尽可能的使用7z格式(rar也可以,不过是商业软件,不推荐)
解决现有的问题的话,比较靠谱的是先解压再转换,比如windows中文环境下的压缩文件到linux下解压,出现乱码的文件名即是 GBK被当做UTF8显示了,我们只要正确转换就行了
convmv -f gb2312 -t utf8 -r --notest *

=============
说句题外话,当年做的病毒木马检测项目,要对所有压缩文件解压缩,由于性能要求和接口原因,不能使用现有的解压缩产品,最后把相关解压缩的源代码都看了遍,zip,rar,7z,cab,tar,gz,ios等等,其中被zip格式的乱码问题折腾的死去活来;一怒之下把字符编码研究了透,还写了一篇博客,邮件乱码、数据库乱码、python程序乱码等,自此妈妈再也不担心我的编码问题了。
也建议大家深入了解下字符编码。



 


(责任编辑:IT)
------分隔线----------------------------