由于 Windows 之间有大量文件交换工作(GBK编码)和 Linux(UTF-8编码),很容易遇到字符编码问题,例如:
- Windows系统中zip/tar文件名中包含中文字符,在Linux系统中解压/untar。
- 运行迁移的旧版 Java Web 应用程序(在 Windows 系统上设计,在 JSP 中使用 GBK 编码),将 GBK 编码命名的文件写入磁盘。
- ftp 在 Windows FTP 服务器和 Linux 客户端之间获取/放置 GBK 编码命名的文件。
- Linux 中切换 LANG 环境。
前面提到的常见问题是文件定位/命名。经过谷歌搜索后,我得到了一篇文章在 Linux 中使用 Unicode https://www.linux.com/news/using-unicode-linux/, 它说:
操作系统和许多实用程序不知道文件名中的字节代表什么字符。
因此,可能有两个具有相同名称的文件(相同的当他们的名字被正确的字符集解码时,但是不同的以字节为单位),例如中文.txt
,但编码不同:
[root@fedora test]# ls
???? 中文
[root@fedora test]# ls | iconv -f GBK
中文
涓iconv: illegal input sequence at position 7
[root@fedora test]# ls 中文 && ls $'\xd6\xd0\xce\xc4' | iconv -f gbk
中文
中文
问题:
- 是否可以使用固定字符编码配置Linux文件系统(例如NTFS无论 LANG/LC_ALL 环境如何,内部使用 UTF-16)来存储文件名?
- 或者,我真正想问的是:是否可以
$'\xe4\xb8\xad\xe6\x96\x87.txt'
在zh_CN.UTF-8环境下让文件名为中文.txt(),$'\xd6\xd0\xce\xc4.txt'
在zh_CN.GBK环境下让文件名为中文.txt()引用同一个文件? - 如果它不可配置,那么是否可以修补内核以在文件系统和当前环境之间转换字符编码(只是一个问题,而不是请求实现)?如果可能的话,性能影响有多大?
答案1
我对你的问题进行了一些重新阐述,原因在你按顺序阅读时应该会很明显。
1. 是否可以配置linux文件系统使用固定字符编码来存储文件名,而不管LANG/LC_ALL环境如何?
不,这是不可能的:正如您在问题中提到的,UNIX 文件名只是一个字节序列;内核对编码一无所知,这完全是用户空间(即应用程序级)概念。
换句话说,内核对LANG
/一无所知LC_*
,因此无法翻译。
2. 是否可以让不同的文件名引用同一个文件?
您可以有多个目录条目引用同一个文件;你可以做到硬链接或者符号链接。
但请注意,在当前编码中无效的文件名(例如,在 UTF-8 语言环境中工作时的 GBK 字符串)将显示得很糟糕(如果有的话)。
3. 是否可以修补内核以在文件系统和当前环境之间转换字符编码?
您无法修补核心来做到这一点(参见 1.),但理论上您可以修补 C 库(例如 glibc)来执行此转换,并且在调用内核时始终将文件名转换为 UTF-8,然后将它们转换回从内核读取文件名时的当前编码。
一种更简单的方法可能是编写一个覆盖文件系统保险丝,在将文件名与 UTF-8 相互转换后,将任何文件系统请求重定向到另一个位置。理想情况下,您可以挂载此文件系统~/trans
,并且当进行访问时
~/trans/a/GBK/encoded/path
,FUSE 文件系统才真正进行访问
/a/UTF-8/encoded/path
。
然而,这些方法的问题是:如何处理文件系统上已存在且不是 UTF-8 编码的文件?你不能只是简单地传递它们而不翻译,因为那样你就不知道如何转换它们;您不能通过将无效字符序列转换为来破坏它们,?
因为这可能会产生冲突......
答案2
您可以做的是将支持的区域设置数量限制为仅 UTF-8 区域设置。
http://www.fifi.org/cgi-bin/man2html/usr/share/man/man5/locale.gen.5
答案3
OEM 代码页选择在 vanilla unzip 和 vanilla p7zip 中均被破坏。我做了补丁解决这个问题并且有适用于 Ubuntu 的 ppa使用应用了此补丁的 p7zip。
答案4
zip 的这个问题已经固定的在最近的far2l 文件和存档管理器。为了让 far2l 的 zip 旧字符集检测正常工作,您的系统语言设置应该与创建存档的系统上设置的语言设置相匹配(Windows 的内部“zip 文件夹”工具使用相同的逻辑)。你也可以做
LANG=zh_CN.UTF-8 far2l