跨平台中文文件名乱码的解决
最近被这个文件名编码问题搞得焦头烂额。
事情的起因是这样的~~
在很久很久以前——大约是2年多年前,我整了一台P3 的机器装了FreeBSD 6.2做服务器,经常用Filezilla的SFTP往里面备份本地的文件,当然也包括一些中文名的文件。一切都很正常,上传下载都没问题,即使是用 SSH连过去用Tar打包再Gzip压缩以后下载下来解开都没问题。
但是好日子在前几天到头了。我前一阵又弄了一台P3的机器装了Ubuntu 7.10。问题出现了:
首 先是在Windows上用Filezilla连接Ubuntu时看到的中文文件名全是乱码,但是用Putty通过SSH连接Ubuntu却是正常的(原先 是乱码,后来改设置为UTF-8编码就好了,不过Filezilla没有类似的设置可改)。如果用Filezilla向Ubuntu上传本地的中文文件, 则在Filezilla里看到Remote端的文件名是正确的,但在Putty里看到是乱码。
然后更严重的问题是:当我在Ubuntu上用 Filezilla的SFTP从FreeBSD上下载文件时发现那些中文文件名都成了乱码。只好改用tar/tar.gz再试,结果还是乱。最后问了 Google,但是结果并不理想,试过很多方法都无法解决,甚至为此特地在FreeBSD和Ubuntu上都装了p7zip试验,也还是不行。
折腾了好几天之后,我才想到应该研究一下几个系统上的locale设置究竟是如何的——坦白说,要不是因为搜到的资料里有提到这方面,我从前还真没注意到这回事。在FreeBSD和Ubuntu上分别运行了locale命令检查的结果是:
FreeBSD的LC_ALL为“C”,即"POSIX"的别名,似乎是一种无固定编码的方案,或者可以认为就是本地编码,默认的设置。
Ubuntu的LC_ALL为“zh_CN.UTF-8”,这个是我设置的。
Windows不必说了,肯定是本地编码——只是我没有想到的是,公司里用的英文版Windows居然也是本地编码,我一直以为是Unicode的,看来是为了保持兼容。
这 样就好理解了,Filezilla不改变编码方式,所以当Remote端与本机的编码不一致时,必然乱码。所以在Windows上用Filezilla连 接Ubuntu看到乱码,而我的Putty因为是设置为UTF-8编码,所以看到的是正确的——因为Ubuntu一端是UTF-8。而如果用 Filezilla上传中文文件,则因为Windows是本地编码,所以上传以后仍然为本地编码(GB系),而Ubuntu是UTF-8所以是乱码。
FreeBSD 那边的问题也是一样的,因为那些文件都是以前从Windows上传上去的,用的都是GB系编码,而早年我用Putty都是用默认的本地编码方案,所以一直 没有发现问题。这样的话,因为FreeBSD是本地编码,与Ubuntu的UTF-8不一致,所以怎么弄都是乱码。
但是据说用7zip这样的工具打包以后是可以解决这样的编码不一致问题的,我试了却没有成功。后来才想明白,因为7zip是根据系统的locale设置来对文件名进行相应的处理,因为原来我处理的时候文件名是GB系的编码,而系统是设置为UTF-8,所以总也不对。
最后的解决方案是:
在ubuntu上用以下命令:
export LC_ALL="zh_CN.GBK"
scp raptor@freebsdserver:/home/raptor/myfiles/*.* .
export LC_ALL="zh_CN.UTF-8"
convmv -f GBK -t UTF-8 --notest *.*
原理就是先把ubuntu的locale改为GBK,然后用SSH COPY文件过来,再改locale为UTF-8,然后用convmv来转换文件名的编码。
不过经过试验表明,不改变locale直接scp也是可以的,因为scp并不会改变文件的编码方式,不过改了locale以后便于在转编码之前检查scp过来的内容(否则scp过来是乱码,要到转编码后才正常)。
这样做的结果就是,这些文件在ubuntu上是正常了,以后要再弄回windows就比较麻烦,需要用7zip之类的工具打包下载再解开。
归根到底这些问题都是因为该死的Windows用本地编码来记录文件名,Unicode化做得不够彻底。