Linux shell和文件系统如何识别Unicode?

时间:2016-08-15 01:21:33

标签: linux shell unicode utf-8

据我所知,Linux文件系统将文件名存储为字节序列,这意味着与Unicode编码无关。

但是,除了UTF-8或增强型UTF-8之外的编码很可能使用0字节作为可以出现在文件名中的Unicode字符的多字节表示的一部分。在Linux文件系统C代码中的任何地方都可以使用0字节终止字符串。那么Linux文件系统如何支持Unicode呢?是否假设所有创建文件名的应用程序仅使用UTF-8?但事实并非如此,是吗?

类似地,shell(例如bash)在模式中使用*来匹配任意数量的文件名字符。我可以在shell C代码中看到它只是使用*的ASCII字节,并逐字节地分隔匹配。对于UTF-8编码的名称很好,因为它具有以下属性:如果你接受字符串的字节表示,那么从开头用*匹配一些字节,并将其余字符与另一个字符串匹配,然后在实际上,开头匹配一串完整字符,而不仅仅是字节。

但是其他编码没有那个属性,是吗?那么shell再次假设是UTF-8吗?

2 个答案:

答案 0 :(得分:6)

确实,UTF-16和其他“宽字符”编码不能用于Linux中的路径名(也不能用于任何其他符合POSIX标准的操作系统)。

原则上是真的,任何人都假定为UTF-8,尽管随着其他编码消失,将来可能会成为现实。 Unix风格的程序假设是 ASCII兼容的编码。具有这些属性的任何编码都是ASCII兼容的:

  • 编码的基本单位是字节,而不是更大的实体。某些字符可能被编码为字节的序列,但必须至少有127个字符仅使用单个字节进行编码,即:
  • 由ASCII定义的字符(现在,这些最好描述为Unicode代码点U + 000000到U + 00007F,包括在内)被编码为单个字节,其值等于其Unicode代码点。
  • 相反,值为0x00到0x7F的字节必须始终解码到ASCII定义的字符,而不管周围的上下文如何。 (例如,字符串0x81 0x2F必须解码为两个字符,无论0x81解码到哪个/。)

UTF-8与ASCII兼容,但所有ISO-8859-n页面,EUC编码以及许多其他页面也是如此。

某些程序可能还需要额外的属性:

  • 作为字节序列查看的字符编码永远不是正确的前缀,也不是任何其他字符编码的正确后缀。

UTF-8有这个属性,但(我认为)EUC-JP没有。

也是许多“Unix风格”程序保留代码点U + 000000(NUL)用作字符串终止符的情况。这在技术上是对编码的约束,而是在文本本身上。 (字节 0x00不出现在字符串中间的密切相关的要求是这样的结果加上要求0x00映射到U + 000000而不管周围的上下文。)

答案 1 :(得分:3)

Linux中没有文件名编码(无论如何都在文件系统的ext系列中)。文件名是字节序列,而不是字符。应用程序可以将这些字节解释为UTF-8或其他任何字节。文件系统并不关心。

POSIX在执行模式匹配时规定shell obeys the locale environment vsriables such as LC_CTYPE。因此,无论编码如何只是比较字节的模式匹配代码都不会与您的假设编码或任何有状态编码兼容。但这似乎并不重要,因为现有语言环境通常不支持此类编码。另一方面,UTF-8似乎得到了很好的支持:在我的实验bash中,?字符与文件名中的单个Unicode字符(而不是单个字节)正确匹配(给定UTF- 8 POSale)按POSIX规定。