命名文件、路径和命名空间

Windows 支持的所有文件系统都使用文件和目录的概念来访问存储在磁盘或设备上的数据。 使用适用于文件和设备 I/O 的 Windows API 的 Windows 开发人员应了解文件和目录名称的各种规则、约定和限制。

可以使用文件 I/O API 从磁盘、设备和网络共享访问数据。 文件和目录以及命名空间是路径概念的一部分,路径是获取数据的位置的字符串表示形式,无论数据来自磁盘、设备还是用于特定操作的网络连接。

某些文件系统(如 NTFS)支持链接文件和目录,它们也遵循文件命名约定和规则,就像常规文件或目录一样。 有关其他信息,请参阅 硬链接和交汇点重新分析点和文件操作

有关其他信息,请参阅以下小节:

若要了解如何配置Windows 10以支持长文件路径,请参阅最大路径长度限制

文件和目录名称

所有文件系统都遵循单个文件的相同常规命名约定:基文件名和可选扩展名,用句点分隔。 但是,每个文件系统(例如 NTFS、CDFS、exFAT、UDFS、FAT 和 FAT32)都可以对目录或文件路径中各个组件的形成具有特定和不同的规则。 请注意, 目录 只是具有指定为目录的特殊属性的文件,否则必须遵循与常规文件相同的所有命名规则。 由于术语 目录 仅指文件系统的特殊类型的文件,因此某些参考资料将使用常规术语 文件 来包含目录和数据文件的概念。 因此,除非另行指定,否则文件的任何命名或使用规则或示例也应应用于目录。 术语 路径 是指一个或多个目录、反斜杠,可能还有一个卷名称。 有关详细信息,请参阅 路径 部分。

字符计数限制也可能不同,并且可能因使用的文件系统和路径名称前缀格式而异。 通过支持向后兼容机制,这进一步复杂化了。 例如,较旧的 MS-DOS FAT 文件系统支持基文件名最多 8 个字符,扩展名最多支持 3 个字符,总共支持 12 个字符(包括点分隔符)。 这通常称为 8.3 文件名。 Windows FAT 和 NTFS 文件系统不限于 8.3 文件名,因为它们具有 长文件名支持,但仍支持 8.3 版本的长文件名。

命名约定

以下基本规则使应用程序能够创建和处理文件和目录的有效名称,而不考虑文件系统:

  • 使用句点将基文件名与目录或文件名称中的扩展名分隔开。

  • 使用反斜杠 (\) 分隔路径组件。 反斜杠将文件名从路径中除以,将一个目录名与路径中的另一个目录名称分开。 不能在实际文件或目录的名称中使用反斜杠,因为它是将名称分隔成组件的保留字符。

  • 根据需要使用反斜杠作为 卷名称的一部分,例如“C:\”在“C:\path\file”或“\\server\share\path\file”中为通用命名约定的“\\server\share” (UNC) 名称。 有关 UNC 名称的详细信息,请参阅 最大路径长度限制 部分。

  • 不要假定区分大小写。 例如,将 OSCAR、Oscar 和 oscar 的名称视为相同,即使某些文件系统 ((如符合 POSIX 的文件系统) 可能认为它们不同)。 请注意,NTFS 支持 POSIX 语义区分大小写,但这不是默认行为。 有关详细信息,请参阅 CreateFile

  • (驱动器号) 的卷指定符同样不区分大小写。 例如,“D:\”和“d:\”引用同一卷。

  • 使用当前代码页中的任何字符作为名称,包括 Unicode 字符和扩展字符集中 (128-255) 字符,但以下各项除外:

    • 以下保留字符:

      • <(小于)
      • >(大于)
      • : (冒号)
      • "(双引号)
      • /(正斜杠)
      • \(反斜杠)
      • | (竖线或竖线)
      • ? (问号)
      • *(星号)
    • 整数值零,有时称为 ASCII NUL 字符。

    • 整数表示形式的字符介于 1 到 31 之间,但允许这些字符的备用数据流除外。 有关文件流的详细信息,请参阅 文件流

    • 目标文件系统不允许的任何其他字符。

  • 使用句点作为路径中的目录 组件 来表示当前目录,例如“.\temp.txt”。 有关详细信息,请参阅 路径

  • 使用两个连续的句点 (。) 作为路径中的目录 组件 来表示当前目录的父目录,例如“.”。\temp.txt”。 有关详细信息,请参阅 路径

  • 不要将以下保留名称用于文件的名称:

    CON、PRN、AUX、NUL、COM0、COM1、COM2、COM3、COM4、COM5、COM6、COM7、COM8、COM9、LPT0、LPT1、LPT2、LPT3、LPT4、LPT5、LPT6、LPT7、LPT8 和 LPT9。 另请避免这些名称紧跟扩展名;例如,NUL.txt 和 NUL.tar.gz 都等效于 NUL。 有关详细信息,请参阅命名空间

  • 不要用空格或句点结束文件或目录名称。 尽管基础文件系统可能支持此类名称,但 Windows shell 和用户界面不支持。 但是,可以接受指定句点作为名称的第一个字符。 例如“.temp”。

短名称与长名称

长文件名被视为超出短 MS-DOS (也称为 8.3) 样式命名约定的任何文件名。 创建长文件名时,Windows 还可以创建名称的短 8.3 格式,称为 8.3 别名 或短名称,并将其存储在磁盘上。 此 8.3 别名可以出于系统范围内或指定卷的性能原因禁用,具体取决于特定的文件系统。

Windows Server 2008、Windows Vista、Windows Server 2003 和 Windows XP:在 Windows 7 和 Windows Server 2008 R2 之前,无法禁用指定卷的 8.3 别名。

在许多文件系统上,文件名将在名称的每个组件中包含一个平铺 (~) ,该组件太长,无法符合 8.3 命名规则。

注意

并非所有文件系统都遵循平铺替换约定,并且系统可以配置为禁用 8.3 别名生成,即使它们通常支持它。 因此,不要假设磁盘上已存在 8.3 别名。

 

若要从系统请求 8.3 文件名、长文件名或文件的完整路径,请考虑以下选项:

  • 若要获取 8.3 格式的长文件名,请使用 GetShortPathName 函数。
  • 若要获取短名称的长文件名版本,请使用 GetLongPathName 函数。
  • 若要获取文件的完整路径,请使用 GetFullPathName 函数。

在较新的文件系统(如 NTFS、exFAT、UDFS 和 FAT32)上,Windows 将长文件名存储在 Unicode 中的磁盘上,这意味着始终保留原始的长文件名。 即使长文件名包含扩展字符,也是如此,无论在磁盘读取或写入操作期间处于活动状态的代码页。

可以在 NTFS 文件系统分区和 Windows FAT 文件系统分区之间复制使用长文件名的文件,而不会丢失任何文件名信息。 对于较旧的 MS-DOS FAT 和某些类型的 CDFS (CD-ROM) 文件系统,这可能不是这样,具体取决于实际文件名。 在这种情况下,如果可能,将替换短文件名。

路径

指定文件 的路径 由一个或多个组件组成,这些 组件由特殊字符 (反斜杠) 分隔,每个组件通常都是目录名称或文件名,但下面讨论了一些明显的例外情况。 对于系统对路径的开头或 前缀的解释,这通常至关重要。 此前缀确定路径使用的 命名空间 ,以及路径中的哪个位置使用了哪些特殊字符,包括最后一个字符。

如果路径的组件是文件名,则它必须是最后一个组件。

路径的每个组件也将受为特定文件系统指定的最大长度的约束。 一般情况下,这些规则分为两类: 。 请注意,目录名称由文件系统存储为特殊类型的文件,但文件的命名规则也适用于目录名称。 总之,路径只是特定文件或目录名称存在的所有目录之间的层次结构的字符串表示形式。

完全限定路径与相对路径

对于操作文件的 Windows API 函数,文件名通常可以相对于当前目录,而某些 API 需要完全限定的路径。 如果文件名不以下列项之一开头,则文件名是相对于当前目录的:

  • 任何格式的 UNC 名称,始终以两个反斜杠字符开头, (“\\”) 。 有关更多信息,请参见下一节。
  • 带反斜杠的磁盘指示符,例如“C:\”或“d:\”。
  • 单个反斜杠,例如“\directory”或“\file.txt”。 这也称为 绝对路径

如果文件名仅以磁盘指示符开头,而不是冒号后的反斜杠,则会将其解释为驱动器上具有指定字母的当前目录的相对路径。 请注意,当前目录可能是根目录,也可能不是根目录,具体取决于该目录在该磁盘上最近执行“更改目录”操作期间所设置的内容。 此格式的示例如下所示:

  • “C:tmp.txt”是指驱动器 C 上当前目录中名为“tmp.txt”的文件。
  • “C:tempdir\tmp.txt”是指驱动器 C 上当前目录的子目录中的文件。

如果路径包含“双点”,则也称其为相对路径:也就是说,两个句点一起位于路径的一个组件中。 此特殊说明符用于表示当前目录上方的目录,也称为“父目录”。 此格式的示例如下所示:

  • "..\tmp.txt“指定名为 tmp.txt 的文件,该文件位于当前目录的父目录中。
  • "..\..\tmp.txt“指定当前目录上方有两个目录的文件。
  • "..\tempdir\tmp.txt“指定名为 tmp.txt 位于名为 tempdir 的目录中的文件,该文件是当前目录的对等目录。

相对路径可以合并这两种示例类型,例如“C:..\tmp.txt”。 这很有用,因为尽管系统会跟踪当前驱动器以及该驱动器的当前目录,但如果系统有多个) ,则系统也会跟踪每个不同驱动器号 (中的当前目录,而不考虑将哪个驱动器指示符设置为当前驱动器。

最大路径长度限制

在Windows 10版本 1607 之前的 Windows 版本中,路径的最大长度为 MAX_PATH,定义为 260 个字符。 在更高版本的 Windows 中,需要更改注册表项或使用组策略工具来删除限制。 有关完整详细信息,请参阅 最大路径长度限制

命名空间

Windows API 中使用的命名空间约定主要有两种类别,通常称为 NT 命名空间Win32 命名空间。 NT 命名空间设计为其他子系统和命名空间(包括 Win32 子系统和 Win32 命名空间)可能存在的最低级别命名空间,并按扩展设计为 Win32 命名空间。 POSIX 是 Windows 中基于 NT 命名空间构建的子系统的另一个示例。 早期版本的 Windows 还为某些特殊设备(例如通信 (串行和并行) 端口)以及默认显示控制台(现在称为 NT 设备命名空间的一部分)定义了多个预定义或保留的名称,并且为了向后兼容,当前版本的 Windows 仍受支持。

Win32 文件命名空间

本部分和下一节汇总了 Win32 命名空间前缀和约定,并介绍了如何使用它们。 请注意,这些示例旨在与 Windows API 函数一起使用,并不一定都适用于 Windows shell 应用程序,例如 Windows 资源管理器。 因此,可能的路径范围比通常从 Windows shell 应用程序提供的路径更广,利用这一点的 Windows 应用程序可以使用这些命名空间约定进行开发。

对于文件 I/O,路径字符串的“\\?\”前缀会告知 Windows API 禁用所有字符串分析,并将其后面的字符串直接发送到文件系统。 例如,如果文件系统支持大型路径和文件名,则可以超过 Windows API 以其他方式强制执行 的MAX_PATH 限制。 有关正常最大路径限制的详细信息,请参阅上一节 最大路径长度限制

由于它关闭了路径字符串的自动扩展,因此“\\?\”前缀还允许在路径名称中使用“..”和“.”,如果尝试将这些保留的相对路径说明符作为完全限定路径的一部分对文件执行操作,这非常有用。

许多但并非所有文件 I/O API 都支持“\\?\”;应查看每个 API 的参考主题才能确定。

请注意,应使用 Unicode API 来确保“\\?\”前缀允许超过 MAX_PATH

Win32 设备命名空间

“\.\”前缀将访问 Win32 设备命名空间,而不是 Win32 文件命名空间。 这是直接访问物理磁盘和卷的方式,而无需通过文件系统(如果 API 支持这种类型的访问)。 可以使用 CreateFileDefineDosDevice 函数 (访问磁盘以外的许多设备,例如) 。

例如,如果要打开系统的串行通信端口 1,可以在 调用 CreateFile 函数时使用“COM1”。 这样做是因为 COM1-COM9 是 NT 命名空间中保留名称的一部分,尽管使用“\\.\”前缀也适用于这些设备名称。 相比之下,如果安装了 100 端口串行扩展板,并且想要打开 COM56,则无法使用“COM56”打开它,因为 COM56 没有预定义的 NT 命名空间。 需要使用“\\.\COM56”打开它,因为“\\.\”直接转到设备命名空间,而无需尝试查找预定义的别名。

使用 Win32 设备命名空间的另一个示例是将 CreateFile 函数与“\\.\PhysicalDriveX” (其中 X 是) 或“\\.\CdRomX”的有效整数值。 这样,你可以绕过文件系统直接访问这些设备。 这之所以有效,是因为这些设备名称是由系统在枚举这些设备时创建的,并且某些驱动程序还会在系统中创建其他别名。 例如,实现名称“C:\”的设备驱动程序有自己的命名空间,恰好也是文件系统。

通过 CreateFile 函数的 API 通常使用“\\.\”前缀,因为 CreateFile 是用于打开文件和设备的函数,具体取决于所使用的参数。

如果使用 Windows API 函数,则应使用“\\.\”前缀来访问设备,而不访问文件。

大多数 API 不支持“\\.\”;只有那些设计为使用设备命名空间的人才能识别它。 请始终查看每个 API 的参考主题以确保。

NT 命名空间

也有一些 API 允许使用 NT 命名空间约定,但 Windows 对象管理器在大多数情况下使这一点变得不必要。 为了说明,使用 Windows Sysinternals WinObj 工具在系统对象浏览器中浏览 Windows 命名空间非常有用。 运行此工具时,看到的是从根目录开始的 NT 命名空间,或“\”。 名为“Global?”的子文件夹是 Win32 命名空间所在的位置。 命名设备对象驻留在“Device”子目录中的 NT 命名空间中。 在这里,还可以找到 Serial0 和 Serial1,这些设备对象表示系统存在的前两个 COM 端口。 表示卷的设备对象类似于“HarddiskVolume1”,尽管数字后缀可能会有所不同。 子目录“Harddisk0”下的名称“DR0”是表示磁盘等的设备对象的一个示例。

为了使这些设备对象可供 Windows 应用程序访问,设备驱动程序会创建符号链接, (符号链接) Win32 命名空间“Global?”,指向其各自的设备对象。 例如,“Global??”子目录下的 COM0 和 COM1 只是到 Serial0 和 Serial1 的符号链接,“C:”是指向 HarddiskVolume1 的符号链接,“Physicaldrive0”是到 DR0 的符号链接,等等。 如果没有符号链接,指定的设备“Xxx”将无法供任何使用 Win32 命名空间约定的 Windows 应用程序使用,如前所述。 但是,可以使用支持格式“\Device\Xxx”的 NT 命名空间绝对路径的任何 API 向该设备打开句柄。

随着通过终端服务和虚拟机添加多用户支持,进一步有必要虚拟化 Win32 命名空间中的系统范围的根设备。 这是通过将名为“GLOBALROOT”的符号链接添加到 Win32 命名空间来实现的,可以在前面讨论的 WinObj 浏览器工具的“Global?”子目录中看到该符号链接,并且可以通过路径“\\?\GLOBALROOT”进行访问。 此前缀可确保其后面的路径在系统对象管理器的真实根路径中查找,而不是与会话相关的路径。

文件系统功能比较