我刚刚读了下面这句话:
区分大小写是 Linux 文件系统的功能,而不是 Linux 操作系统的功能。
我从这句话中推断出,如果我使用的是 Linux 计算机,但我使用的是使用 Windows 文件系统格式化的设备,那么区分大小写就不是问题。
我尝试了以下方法来验证这一点:
$ ~/Documents: mkdir Test temp
$ ~/Documents: touch Test/a.txt temp/b.txt
$ ~/Documents: ls te*
b.txt
它只列出了目录中的文件temp
,这是预期的,因为我位于 Linux 文件系统中。
当我导航到 Windows 文件系统时(注意:我使用的是 WSL2),我仍然得到相同的结果,但我期望它列出两个目录中的文件,忽略区分大小写。
$ /mnt/d: mkdir Test temp
$ /mnt/d: touch Test/a.txt temp/b.txt
$ /mnt/d: ls te*
b.txt
我用 bash 和 zsh 都试过了。
我觉得它在某种程度上与 bash (或 zsh)有关,因为我还读到,即使在使用不区分大小写的文件系统时,bash 也会强制区分大小写。
该测试适用于 Powershell,因此这意味着文件系统确实不区分大小写。
答案1
在这里,你正在运行:
ls te*
使用您的某个功能壳被称为通配或者文件名生成(POSIX 中的路径名扩展),不是 Linux 系统的路径名,也不是 Linux 上使用的任何文件系统的路径名。
te*
被扩展通过外壳到与该模式匹配的文件列表。
为此,shell 从系统请求当前目录中的条目列表(通常使用readdir()
C 库的函数,该函数在下面将使用特定于系统的系统调用(getdents()
在 Linux 上)),然后将每个名称与模式。
除非您已将 shell 配置为不区分大小写地匹配(请参阅nocaseglob
zsh 或 bash 中的选项)或使用 glob 运算符来切换不区分大小写(如(#i)
中的扩展 glob 运算符zsh
),否则te*
只会扩展到名称为由readdir()
开头报告te
,即使系统或下面的文件系统上的路径名解析不区分大小写或可以设置为类似于 NTFS。
答案2
作为Vojtech 解释, NTFS 区分大小写。在 FAT 文件系统上尝试可以,但前提是您使用大小写折叠变体,IE msdos
在 Linux 上(我不知道 WSL 上是否有等效的)。对于这种 FAT 变体,文件名都是小写的,因此Test
显示为test
.
关于文件系统中的大小写敏感性,需要考虑多个方面:
- 文件系统本身是否存储案例信息;
- 文件系统的预期使用是否考虑大小写;
- 无论是文件系统驱动程序还是操作系统映射大小写,IE是否可以忽略大小写找到文件;
- 如何来映射案例。
历史 FAT,如 中实现的msdos
,介于前两者之间:从技术上讲,FAT 可以存储大小写,但实际上并没有以这种方式使用,并且 MS-DOS 及其克隆折叠了大小写(因此readme.txt
和README.TXT
都是ReAdMe.TxT
有效的)访问方式README.TXT
)。 Windows 保留了此行为,即使在保留大小写的文件系统(包括 VFAT 和 NTFS)上也是如此。文件msdos
系统驱动程序通过将所有文件名映射为小写来处理此问题,这不太正确,但会产生一致的结果,并避免与 Unix 风格的工具和用户的期望相关的问题。因此,在 Linux 上,使用驱动程序挂载文件系统msdos
意味着README.TXT
只能通过 访问readme.txt
,而不能通过包括上面所示的任何变体进行访问。
你的引用源于这样一个事实:Linux核心本身并不特别关心,至少在表面上是这样:人们可以想象一个文件系统,其中open("README.TXT")
和open("ReAdMe.TxT")
会打开同一个文件。事实上,XFS 可以以这种方式配置,至少对于 ASCII 文件名(它会保留大小写,但提供不区分大小写的查找)。然而,对于通用场景来说,事情很快就会变得更加复杂,多年来已经有很多讨论;参见例如文件系统和不区分大小写,不区分大小写的文件系统查找, 和不区分大小写的 ext4在 LWN 上。
答案3
那是因为NTFS 也区分大小写,但 Windows 对用户隐藏它。 FAT 不区分大小写,您可以通过尝试在同一目录中创建test
和目录来检查:Test
$ ls
test
$ mkdir Test
mkdir: cannot create directory ‘Test’: File exists
$ mkdir TEST
mkdir: cannot create directory ‘TEST’: File exists
它实际上比这个和你的更复杂一点ls
使用 FAT,您的测试也无法工作,因为它实际上是案例保留-- 它不允许您创建Test
和目录,但它仍然在这两种情况之间(以及在和之间)test
有所区别,因此for和不会列出两者的内容。T*
t*
ls t*
test
Temp
答案4
有一点值得特别指出,它可能会将其中一些答案放在上下文中。
在 Linux 上,所有处理文件名的系统调用都处理字节字符串。也就是说,每当程序要求对文件系统执行某些操作时,它都会将其正在使用的任何文件名指定为字节字符串,并且返回给它的任何文件名都将是字节字符串。通常(尽管这不是强制的),这些字符串将包含 ASCII 或 UTF-8 编码的文本,并且这些编码中大写和小写字母的二进制表示是不同的。因此,任何将文件名视为“只是二进制数据”的内容都是区分大小写的。
一旦这些请求到达文件系统驱动程序,某些文件系统将区分大小写解释文件名(通常为 Linux 或其他 Unix 操作系统创建),而某些文件系统将不区分大小写解释文件名(通常为其他操作系统创建,例如 Windows) 。但这些是程序看不到的内部实现细节——它们看到的只是字节串。
通常,程序不会尝试确定它们运行的文件系统是否区分大小写,并且许多程序将隐式假设文件系统区分大小写(因为这是最容易实现的)。有些可能有配置选项来允许它们处理大小写,但请记住,所有文件系统将与它们谈论的都是字节字符串,因此程序无法根据它们看到的文件名计算出这些内容。