linux上文件系统字符编码的几个问题

Liu*_* 刘研 12 linux filesystems character-encoding filenames

由于Windows(GBK编码)和Linux(UTF-8编码)之间有大量的文件交换工作,所以很容易遇到字符编码问题,例如:

  • zip/tar 文件名在 Windows 系统中包含中文字符,在 Linux 系统中解压/解压。
  • 运行迁移的遗留 Java Web 应用程序(在 Windows 系统上设计,在 JSP 中使用 GBK 编码)将 GBK 编码命名的文件写入磁盘。
  • ftp 在 Windows FTP 服务器和 Linux 客户端之间获取/放置 GBK 编码命名的文件。
  • 在 Linux 中切换 LANG 环境。

前面提到的常见问题是文件定位/命名。谷歌搜索后,我得到了一篇文章Using Unicode in Linux https://www.linux.com/news/using-unicode-linux/,它说:

操作系统和许多实用程序没有意识到文件名中的字节代表什么字符。

因此,可能有两个具有相同名称的文件(当它们的名称由正确的字符集解码时为SAME,但以字节为单位不同),例如??.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
??
??
Run Code Online (Sandbox Code Playgroud)

问题:

  1. 是否可以配置 linux 文件系统使用固定字符编码(如NTFS 在内部使用 UTF-16)来存储文件名,而不管 LANG/LC_ALL 环境如何?
  2. 或者,我真正想问的是:是否可以让$'\xe4\xb8\xad\xe6\x96\x87.txt'zh_CN.UTF-8 环境中的文件名 ??.txt ( $'\xd6\xd0\xce\xc4.txt') 和 zh_CN.GBK 环境中的文件名 ??.txt ( )引用同一个文件
  3. 如果它不可配置,那么是否可以修补内核以在文件系统和当前环境之间转换字符编码(只是一个问题,而不是请求实现)?如果可能的话,性能影响有多大?

Ric*_*rri 8

我对您的问题进行了一些重新表述,原因在您按顺序阅读时应该很明显。

1. 是否可以将 linux 文件系统配置为使用固定字符编码来存储文件名,而不管 LANG/LC_ALL 环境如何?

不,这是不可能的:正如您在问题中提到的,UNIX 文件名只是一个字节序列;内核对编码一无所知,这完全是一个用户空间(即应用程序级)概念。

换句话说,内核对LANG/一无所知LC_*,因此无法进行翻译。

2. 可以让不同的文件名指向同一个文件吗?

您可以有多个目录条目引用同一个文件;你可以通过硬链接符号链接来实现

但是请注意,在当前编码中无效的文件名(例如,当您在 UTF-8 语言环境中工作时的 GBK 字符串)会显示得很糟糕,如果有的话。

3. 是否可以修补内核以在文件系统和当前环境之间转换字符编码?

您无法修补内核来执行此操作(请参阅 1.),但理论上您可以修补 C 库(例如 glibc)以执行此转换,并在调用内核时始终将文件名转换为 UTF-8,并在从内核读取文件名时将它们转换回当前编码。

一种更简单的方法是使用FUSE编写覆盖文件系统,它只是在将文件名转换为 UTF-8 或从 UTF-8 转换后将任何文件系统请求重定向到另一个位置。理想情况下,您可以将这个文件系统挂载到 中~/trans,当访问时 ~/trans/a/GBK/encoded/path,FUSE 文件系统真正访问 /a/UTF-8/encoded/path

但是,这些方法的问题在于:您如何处理文件系统中已存在且未采用 UTF-8 编码的文件?你不能只是简单地将它们未经翻译地传递,因为那样你就不知道如何转换它们;您不能通过将无效字符序列转换为来破坏它们,?因为这可能会造成冲突......

  • 存在这样一个覆盖文件系统:[Convmvfs](http://fuse-convmvfs.sourceforge.net/)。 (4认同)