大小写敏感知多少

大小写敏感(case sensitive)或大小写不敏感(case insensitive)是软件开发中常常被忽略而又偶尔造成困扰的基础问题。这里做一个简单的问题汇总。

先扫个盲:

  1. 所谓大小写是否敏感,即是否区分大小写,敏感意味着区分,不敏感意味着不区分。
  2. “大小写不敏感但大小写保留(case preserving)”,是指操作系统虽然把 abcABC 视为同一个文件或文件夹,但内部保留区分,如果已经存在 abc.txt,则无法再新建 ABC.TXT

系统是否区分大小写

某个操作系统是否区分大小写,取决于实际使用的文件系统(常见操作系统的文件系统,参见附录)。

像 macOS,在格式化磁盘时支持选择多种文件系统格式,同时也支持选择【区分大小写】、【日志式】、【加密】等配置,如果没有手动更改,默认不区分大小写。Windows 的 NTFS 默认不区分大小写,如果使用了 WSL,那对应的 Linux 子系统区分大小写。

  • Windows 使用的 NTFS 和 FAT 系列文件系统,默认大小写不敏感但大小写保留
  • macOS 使用的 APFS 和 HFS+ 文件系统,默认大小写不敏感但大小写保留
  • Linux 使用的 ext3/ext4 文件系统,默认大小写敏感

在 Git 中的实践

Git 默认不区分文件名大小写,如果平常不注意文件的大小写,在实际使用中可能会遇到这样的问题:

  1. 代码仓库中存在路径为 timeLine/TimeLine.jsx 的文件,本地修改为 timeline/Timeline.jsx,执行 git status 不会提示文件改动。

  2. 团队中有人在 Linux 系统上开发,他无视了已经存在的 timeLine/TimeLine.jsx 文件,创建了新的 timeline/Timeline.jsx 文件,并提交到了部署在 Linux 上的 Git 服务器。

  3. Git 服务器上同时存在 timeline/Timeline.jsxtimeLine/TimeLine.jsx 文件,在 Windows 或 macOS 上开发的人,无法正常拉取到两个文件。

因此强烈建议关闭 Git 的忽略大小写功能:

# 全局设置
git config --global core.ignorecase false
# 只设置当前仓库
git config core.ignorecase false

在 Windows 或 macOS 上重命名大小写时,使用 git mv

git mv --force TimeLine.jsx Timeline.jsx
# `--force` 可以简写成 `-f`
git mv -f TimeLine.jsx Timeline.jsx

在 webpack 中的实践

由于 Windows 和 macOS 默认不区分大小写,对于文件 fileName.js,以下几行代码 webpack 编译不会报错:

  • require('fileName.js') 正确的文件名
  • require('FileName.js') 写错文件名
  • require('filename.js') 写错文件名

但是使用部署在 Linux 上的 CI/CD 工具时,webpack 会无法找到后两行代码引用的模块。

因此建议安装 case-sensitive-paths-webpack-plugin 插件,强制检查文件路径大小写。

HTTP Header 区分大小写吗

HTTP Header 的名称字段不区分大小写。HTTP/2 多了额外的限制,因为增加了头部压缩,要求在编码前必须转成小写。

HTTP/1.1 [RFC 7230] 中的描述:

Each header field consists of a case-insensitive field name followed by a colon (":"), optional leading whitespace, the field value, and optional trailing whitespace.

HTTP/2 [RFC 7540] 中的描述:

Just as in HTTP/1.x, header field names are strings of ASCII characters that are compared in a case-insensitive fashion. However, header field names MUST be converted to lowercase prior to their encoding in HTTP/2. A request or response containing uppercase header field names MUST be treated as malformed (Section 8.1.2.6).

HTTP Method 区分大小写吗

HTTP Method 区分大小写,且全部大写。

HTTP/1.1 [RFC 7230] 中的描述:

The method token indicates the request method to be performed on the target resource. The request method is case-sensitive.

URL 区分大小写吗

HTTP 协议和域名不区分大小写,path/query/fragment 区分。

HTTP/1.1 [RFC 7230] 中的描述:

The scheme and host are case-insensitive and normally provided in lowercase; all other components are compared in a case-sensitive manner.

更具体的描述需要参考 URL 的相应标准 Uniform Resource Identifier (URI): Generic Syntax [RFC 3986]

邮箱地址区分大小写吗

参考 URL 标准,邮箱中的域名不区分大小写。用户名是否区分大小写,取决于电子邮件服务商。

HTML 区分大小写吗

HTML 标签、属性名称等一般不区分大小写,具体参考 HTML Living Standard

CSS 区分大小写吗

CSS 属性名称不区分大小写,具体参考 CSS Syntax Module Level 3 和更细致的 CSS 模块标准。

附录

常见文件系统

  • Microsoft 系
    • FAT, File Allocation Table 主要应用于 MS-DOS 系统
      • FAT12
      • FAT16 不支持 2G 及其更大的文件
      • FAT32 适用于闪存,不支持 4G 及其更大的文件,容易产生磁盘碎片,需要定期进行磁盘碎片整理
      • exFAT, Extended File Allocation Table 主要应用于 Windows NT 内核系统,不是日志文件系统,使用过程中断电可能会导致数据丢失
    • HPFS, High Performance File System 主要应用于由 Microsoft 和 IBM 开发的 OS/2 操作系统
    • NTFS, New Technology File System 日志文件系统,主要应用于 Windows NT 内核系统
    • ReFS, Resilient File System 适用于 Windows Server 服务器
  • Apple 系
    • MFS, Macintosh File System 主要应用于 Mac OS 系统
    • HFS, Hierarchical File System 主要应用于 Mac OS 系统
      • HFS+, Hierarchical File System Plus 主要应用于 Mac OS 系统,在系统中显示为“Mac OS Extended(Mac OS 扩展)”,支持日志
    • APFS, Apple File System 主要应用于 macOS 系统,优化闪存/SSD 存储
  • Linux 系
    • ext, extended filesystem 非日志文件系统
    • ext2, second extended filesystem 非日志文件系统
    • ext3, third extended filesystem 日志文件系统
    • ext4, fourth extended filesystem 日志文件系统
  • Unix 系
    • XFS, XFS File System 由 Silicon Graphics 为 IRIX 操作系统开发
    • ZFS, Zettabyte File System 最初由 Sun 公司为 Solaris 10 操作系统开发

相关链接