perl脚本解决zip中文文件名乱码
时间:2010-09-18 来源:BinChengfei
虽然zip诞生之初只支持cp437,但对UTF-8的支持早已加入zip格式的标准之 中,原本这样就该天下太平了。但这个世界爱自作主张和固守陈规的软件太多了,尤其是悲剧只发生在Linux用户的头上的时候(当然Win用户从JP下回的 zip乱码的可能性也有,不过Win下JP的东西什么都是乱码,所以无所谓了)。于是常常会解压一个zip得到一大堆乱码的文件,如果运气好的话,可以 convmv解决;但是遇到解压完的文件名里有一堆的“(invalid encoding)”,那convmv也回天乏术;更不幸的是直接解压不能,说什么
checkdir error: cannot create ?R?X?v???-?^?Wblabla |
Invalid or incomplete multibyte or wide character |
unable to process ?R?X?v???-?^?Wbalbla/gao. |
早先的unzip,比如UnZip 5.52,有个在usage, help和manpage等各种文档中都没提到的神秘参数-O可以指定文件名的编码,从而解决GBK/BIG5/shift_JIS等编码的乱码问题。比如:
unzip -O CP936 怎样打飞机.zip |
可是到了新版本的unzip,比如UnZip 6.00,这个-O参数便名花有主了,而原来的-O功能似乎神隐了。用力搞了很久没搞定,最后求助perl。利用Archive::Zip和Encode,写了个简短的脚本,这个问题瞬间解决。
view sourceprint?01 | #!/usr/bin/perl |
02 |
03 | use Archive::Zip; |
04 | use Encode qw(decode encode); |
05 |
06 | sub usage { |
07 | print <<USAGE; |
08 | USAGE: unzip.pl ZIPFILE [FROMCODE=utf-8 [TOCODE=utf-8]] |
09 | USAGE |
10 | exit; |
11 | } |
12 |
13 | usage unless -e $ARGV[0]; |
14 | $zip = Archive::Zip->new($ARGV[0]); |
15 | $from = $ARGV[1] || 'utf-8'; |
16 | $to = $ARGV[2] || 'utf-8'; |
17 |
18 | for ($zip->memberNames()) { |
19 | $member = $zip->memberNamed($_); |
20 | $_ = encode($to, decode($from, $_)); |
21 | $zip->extractMember($member, $_); |
22 | } |
现在只要
perl unzip.pl 怎样打飞机.zip GBK |
就能顺利解压了。至于开头提到的原因不明的乱码造成的解压不能的情况,可以直接将$_ = encode($to, decode($from, $_))这句修改文件名的代码替换为s#.*?/#gao/#等能解决问题的代码。
Ubuntu Locale配置问题根源解决之道
作者:水滴石穿常见错误
1. No such file 用locale命令的时候就会出现
locale: Cannot set LC_CTYPE to default locale: No such file or directory
locale: Cannot set LC_MESSAGES to default locale: No such file or directory
locale: Cannot set LC_ALL to default locale: No such file or directory
2. perl warning, please check if supported 在apt-get install/remove的时候出现
perl: warning: Please check that your locale settings: LC_ALL = (unset), LC__FASTMSG = "true", LC_MESSAGES = "", LANG = "zh_CN" are supported and installed
相关命令
locale 查看现在的locale配置环境
localepurge 配置需要的locale(如果没有这个命令,用apt-get install localepurge安装)
locale-gen 生成需要的locale文件,
参数 --purge用来删除所有旧的配置,在出现问题时很有用
相关的文件
其实在man locale-gen和man locale里面都讲到了,我还在网上查资料,浪费时间,悔之晚矣……
/usr/share/i18n/SUPPORTED
List of supported values (and their associated encoding) for the
locale name. This representation is recommended over
--all-locales one, due being the system wide supported values.
/var/lib/locales/supported.d/*
List all locales to generate. File format is similar to /usr/share/i18n/SUPPORTED.
/usr/lib/locale/<locale_name>/LC_*
Compiled locale data.这些就是用locale-gen编译出的locale文件了
/etc/environment 编辑这个文件可以手动配置locale环境变量,LC_CTYPE之类的,具体有哪些可配置的变量,都是什么含义,用man locale就能看到了
解决问题
很简单,重新生成所有的locale配置,其实网上的资料只是漏掉了--purge参数而已
第一步:配置自己想要的locale。普遍推荐的方法是拷贝所有ubuntu支持的locale到自己的配置文件里,然后编辑。
cp /usr/share/i18n/SUPPORTED /var/lib/locales/supported.d/local
vi /var/lib/locales/supported.d/local,用dd命令删啊删,只留下en_系列和zh_系列, 或者其他你要的locale
rm /var/lib/locales/supported.d/en
rm /var/lib/locales/supported.d/zh 这两个文件跟local一样功能,也可以把en系列写在en文件里,zh系列写在zh文件里,分类方便而已。我既然都写在local里,这两个就用不着了。
第二步:重新生成locale支持文件
locale-gen --purge
这一步会将/usr/lib/locale/里面的locale支持文件删掉,重新生成。如果设置的locale没有生成过,或者设置的时候拼写错误,在这个目录找不到同名的支持文件就会提示No such file了。
第三步:配置locale环境。
敲locale把输出的那些环境变量拷贝到/etc/environment里面,自己手工修改。可以设的值就是/var/lib/locales/supported.d/local里面包括的值,或者生成在/usr/lib/locale/里面的文件夹名称。
第四步:退出重新登录,再敲locale看看,没错误了。
相关阅读 更多 +