Windows区分大小写

前言

本文整理自当时的 Windows/WSL 文档。相关命令仍有参考价值,但具体行为可能会随 Windows 和 WSL 版本变化,请以当前官方文档为准。

今天终于等来了某个源码仓库的更新,于是急匆匆地合并到本地,结果出现了大量冲突。检查后发现,对方把部分目录名改成了小写字母,更麻烦的是没有完全改干净,导致仓库里同时存在新旧目录名,例如一部分文件在 application,另一部分文件在 Application。好在从 Windows 10 内部版本 17107 开始,Windows 已经支持按目录开启区分大小写。

简略步骤

  1. 新建一个目录(必须是空目录)。
  2. 以管理员身份运行 PowerShell,并执行下方命令。
  3. 将代码重新克隆到新目录,再合并新代码。
  4. 把大小写混用的目录统一改成新的名称。
1
2
# 将 <path> 替换为文件路径,如 C:\Users\user1\
fsutil.exe file setCaseSensitiveInfo <path> enable

参考资料

以下内容整理自微软官方文档。

Windows 和 Linux 区分大小写之间的差异

使用 Linux 和 Windows 文件和目录时,可能需要调整区分大小写的处理方式。

标准行为:

  • Windows 文件系统默认将文件和目录名称视为不区分大小写。FOO.txtfoo.txt 会被视为等效文件。
  • Linux 文件系统默认将文件和目录名称视为区分大小写。FOO.txtfoo.txt 会被视为不同文件。
    Windows 文件系统支持通过属性标志按目录设置区分大小写。虽然默认行为是不区分大小写,但可以为特定目录分配属性标志,使它能够识别仅大小写不同的 Linux 文件和文件夹。

在将驱动器挂载到适用于 Linux 的 Windows 子系统(WSL)文件系统时,这一点尤其重要。在 WSL 文件系统中工作时,运行环境是 Linux,因此文件和目录默认会被视为区分大小写。

备注
过去,如果多个文件的名称仅大小写不同,Windows 将无法正确访问这些文件,因为 Windows 应用程序通常会把文件系统视为不区分大小写,也就无法区分这些名称。即使 Windows 文件资源管理器同时显示了两个文件,无论选择哪一个,最终也可能只会打开同一个文件。

更改文件和目录的区分大小写

下面的步骤说明如何修改 Windows 文件系统上的目录,使其区分大小写,并能够识别仅大小写不同的文件和文件夹。

警告
某些 Windows 应用程序默认假定文件系统不区分大小写,因此可能不会使用准确的大小写来引用文件。例如,应用程序把文件名统一转换为大写或小写并不少见。在标记为区分大小写的目录中,这些应用程序可能会因此无法访问对应文件。另外,如果 Windows 应用程序在区分大小写的目录树中创建新目录,新目录不一定会自动区分大小写。这可能导致 Windows 工具在这类目录中表现异常,因此修改区分大小写设置时需要谨慎。

检查当前区分大小写

若要检查 Windows 文件系统中的目录是否区分大小写,请运行以下命令:

1
fsutil.exe file queryCaseSensitiveInfo <path>

<path> 替换为实际文件路径。对于 Windows(NTFS)文件系统中的目录,<path> 类似于 C:\Users\user1\case-test。如果当前已经位于 user1 目录中,也可以直接运行:fsutil.exe file setCaseSensitiveInfo case-test

修改区分大小写

自 Windows 10 内部版本 17107 开始,Windows 支持按目录开启区分大小写。在 Windows 10 内部版本 17692 中,这项能力进一步扩展,支持从 WSL 内检查和修改目录的区分大小写标志。区分大小写状态通过名为 system.wsl_case_sensitive 的扩展属性公开:不区分大小写的目录值为 0,区分大小写的目录值为 1。

更改目录的区分大小写需要提升权限,也就是以管理员身份运行。修改区分大小写标志还要求当前用户对该目录具有“写入属性”、“创建文件”、“创建文件夹”和“删除子文件夹和文件”权限。更多信息请参阅疑难解答部分。

若要让 Windows 文件系统中的目录区分大小写(FOO ≠ foo),请以管理员身份运行 PowerShell,并执行以下命令:

1
fsutil.exe file setCaseSensitiveInfo <path> enable

若要把 Windows 文件系统中的目录恢复为默认的不区分大小写(FOO = foo),请以管理员身份运行 PowerShell,并执行以下命令:

1
fsutil.exe file setCaseSensitiveInfo <path> disable

只有空目录才能修改区分大小写标志。对于包含仅大小写不同的文件或文件夹的目录,不能禁用区分大小写标志。

区分大小写的继承性

创建新目录时,新目录会继承父目录的区分大小写设置。

警告
在 WSL 1 模式下运行时,这个继承策略存在例外。当发行版以 WSL 1 模式运行时,每个目录的区分大小写标志不会自动继承;在区分大小写目录中创建的新目录也不会自动区分大小写,必须为每个目录显式设置。

用于在 WSL 配置文件中装载驱动器的区分大小写选项

通过 WSL 配置文件挂载驱动器时,也可以管理区分大小写行为。每个已安装的 Linux 发行版都可以拥有自己的 WSL 配置文件,文件名为 /etc/wsl.conf。关于挂载驱动器的更多信息,可以参考开始在 WSL 2 中装载 Linux 磁盘

若要在挂载驱动器时通过 wsl.config 文件配置区分大小写选项:

  1. 打开要使用的 Linux 发行版,例如 Ubuntu。
  2. 切换目录,直到看到 etc 文件夹(可能需要从 home 目录执行 cd ..)。
  3. 列出 etc 目录中的文件,确认 wsl.conf 文件是否已经存在。可以使用 ls 命令,也可以通过 explorer.exe . 用 Windows 文件资源管理器查看当前目录。
  4. 如果 wsl.conf 文件尚不存在,可以使用 sudo touch wsl.conf 创建,或者运行 sudo nano /etc/wsl.conf,在 Nano 编辑器中保存时创建该文件。
  5. 将以下选项添加到 wsl.config 文件中:

默认设置:dir,用于按目录启用区分大小写。

1
2
[automount]
options = case = dir

不区分大小写:off,挂载的 NTFS 驱动器上的所有目录都不区分大小写。

1
2
[automount]
options = case = off

强制区分大小写:force,将 NTFS 驱动器上的所有目录都视为区分大小写。

1
2
[automount]
options = case = force

此选项仅在以 WSL 1 运行的 Linux 发行版挂载驱动器时受支持,并且可能需要添加注册表项。若要添加注册表项,可以在提升权限的命令提示符中执行:reg.exe add HKLM\SYSTEM\CurrentControlSet\Services\lxss /v DrvFsAllowForceCaseSensitivity /t REG_DWORD /d 1

修改 wsl.conf 文件后,需要重新启动 WSL 才能让配置生效。可以使用以下命令关闭并重启 WSL:wsl --shutdown

提示
若要为所有驱动器设置统一的区分大小写挂载选项,也就是通过 DrvFs 文件系统插件让磁盘挂载到 /mnt 下,例如 /mnt/c/mnt/d,请按上文修改 /etc/wsl.conf。若要为某个特定驱动器设置默认挂载选项,请使用 /etc/fstab 文件指定这些选项。更多 WSL 配置项可以参考使用 wslconf 配置每个发行版的启动设置

更改装载到 WSL 发行版的驱动器的区分大小写

默认情况下,挂载到 WSL 发行版中的 NTFS 驱动器不区分大小写。若要修改挂载到 WSL 发行版(例如 Ubuntu)中的驱动器目录的区分大小写,请按照上文针对 Windows 文件系统的相同步骤操作。(默认情况下,EXT4 驱动器区分大小写。)

若要在目录上启用区分大小写(FOO ≠ foo),请使用以下命令:

1
fsutil.exe file setCaseSensitiveInfo <path> enable

若要在目录上禁用区分大小写并恢复默认的不区分大小写(FOO = foo),请使用以下命令:

1
fsutil.exe file setCaseSensitiveInfo <path> disable

备注
如果在 WSL 运行期间修改已挂载驱动器上现有目录的区分大小写标志,请确保 WSL 没有引用该目录,否则修改可能不会生效。也就是说,不能有任何 WSL 进程打开该目录,也不能把该目录或其子目录作为当前工作目录。

使用 Git 配置区分大小写

Git 也提供了一个配置项,用于调整文件名区分大小写的处理方式。如果正在使用 Git,可能还需要调整 git config core.ignorecase

若要将 Git 设置为区分大小写 (FOO.txt ≠ foo.txt),请输入:

git config core.ignorecase false

若要将 Git 设置为不区分大小写 (FOO.txt = foo.txt),请输入:

git config core.ignorecase true

在不区分大小写的文件系统上,将该选项设置为 false 可能导致错误提示、虚假冲突或重复文件等问题。

有关详细信息,请参阅 Git 配置文档

故障排除

我的目录包含大小写相混合的文件,需要区分大小写,但 Windows FS 工具无法识别这些文件

若要使用 Windows 文件系统工具处理包含大小写混用文件的 Linux 目录,需要先创建一个全新的目录并将其设置为区分大小写,然后再把文件复制到该目录中,例如使用 git clone 或 untar。这些文件仍会保留原本的大小写。(如果已经尝试把文件移动到不区分大小写的目录,并且发生了冲突,那么部分文件很可能已经被覆盖,无法再恢复。)

错误:目录不为空

不能直接修改包含文件或子目录的目录的区分大小写设置。可以先创建一个新目录,修改它的设置,然后再把大小写混用的文件复制进去。

错误:访问被拒绝

请确认当前用户对目标目录拥有“写入属性”、“创建文件”、“创建文件夹”和“删除子文件夹和文件”权限。若要检查这些权限,可以在 Windows 文件资源管理器中打开该目录(也可以在命令行中执行 explorer.exe . 打开当前目录),右键单击目录并选择“属性”,再选择“编辑”查看或修改目录权限。

Properties windows to view or change permissions on NTFS directories

错误:此操作需要本地 NTFS 卷

只能在 NTFS 文件系统中的目录上设置区分大小写属性。默认情况下,WSL(Linux)文件系统中的目录区分大小写,不能使用 fsutil.exe 工具将其设置为不区分大小写。

文章作者: Ender
文章链接: https://www.fengyeju.net/archives/windows-adjust-case-sensitivity
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 枫叶居