有关linux与windows中文件名的编码问题总结

最近在整理各类裤子,因为太大用了ntfs-3g挂载硬盘,拷贝到了centos服务器上,结果没有注意文件名的编码问题,总要修改因此说config/i18n配置文件,并且经过ssh链接要常常切换客户端的字符集,无奈,拷回硬盘上,在window上弄吧,结果,文件名出现各类乱码。。。。崩溃了。安心学习了。。。linux

(其中涉及到了ntfs-3g,ssh远程客户端,以及linux的/etc/sysconfig/i18n配置,没有一一测试,除了ntfs-3g不知道是否涉及字符集,其余都涉及到了,思路比较乱,想到哪写到哪了)windows

问题根源:因为Linux与windows采用了不一样的字符集来处理中文文件名,Linux用了utf-8而windows用了gbk,进而致使文件名处理的混乱。centos

个人作法是:服务器

一、利用convmv 在linux上将全部文件名编码转换为gbk,再经过ntfs-3g将文件拷到移动硬盘,最后拷回电脑,在windows上可以正常显示。ssh

二、处理文件工具

三、将文件拷回linux学习

四、利用convmv将文件名转回utf8测试

因为习惯了在windows上开发, 想本身写一个py脚本实如今windows上将文件名字符编码进行转换的功能,可是立刻问题就出现了。编码

下面请看:spa

def conv_gbk_to_utf8(path):
    if os.path.exists(path):
        print 'converting filename to utf8...'
    else:
        print 'The path is invalid!'
        return -1
    for root, dirs, files in os.walk(path):
        for filename in files:
            charset = chardet.detect(filename)
            if charset.get('encoding') in ['utf-8', 'ascii']:
                continue
            else:
                print charset
                conv_filename = filename.decode('gbk').encode()
                res_filename = os.path.join(root, filename)
                conv_filename = os.path.join(root, conv_filename)
                shutil.move(res_filename, conv_filename)
    # modified the charset of name of the dirs
    for root, dirs, files in os.walk(path):
        for dir in dirs:
            charset = chardet.detect(dir)
            if charset.get('encoding') in ['utf-8', 'ascii']:
                continue
            else:
                conv_dir = dir.decode('gb2312').encode()
                res_dir = os.path.join(root, dir)
                conv_dir = os.path.join(root, conv_dir)
                print res_dir, conv_dir
                shutil.move(res_dir, conv_dir)

对于通常的文件名都没问题,可是因为windows对文件命名有着一个限制。就是 ? : " < > 等符号没法被做为合法字符。

那么当一个名为 新建文件夹 的文件夹 ,将字符集从gbk转换为utf8以后,会显示为:鏂板缓鏂囦欢澶, 其编码为:E6 96 B0 E5 BB BA E6 96 87 E4 BB B6 E5 A4 B9 ,若是用编辑工具转换发现实际转换后的字符应该是鏂板缓鏂囦欢澶? B9被丢弃了。

结论:在用程序转换后,出现的特殊字符,会被操做系统丢弃,于是也没法复原。因此这种方法,目前走不通。。。也隐约证实了,为何以前在网上搜索文件名编码转换工具都找不到了吧。。。。

ps:回去又研究了下,shutil.move的实现方法是对文件直接调用os.rename对文件夹采用copytree和rmtree来实现重命名目录的。在copytree中调用了

os.makedirs(dst)

而后调用了nt.py中的

mkdir(name, mode)

 

这步是有c实现的底层库,而在这步就会产生丢字节B9的现象,所以若是想实现此功能须要修改底层实现。 

相关文章
相关标签/搜索