为什么Windows中存在260个字符的路径长度限制?


390

我在不合时宜的时刻遇到了几次这个问题:

  • 尝试处理具有深层路径的开源Java项目
  • 在源代码管理中存储Deep Fitnesse Wiki树
  • 尝试使用Bazaar导入我的源代码管理树时出错

为什么存在此限制?

为什么还没有删除它?

您如何应对路径限制?不,切换到Linux或Mac OS X并不是此问题的有效答案;)


8
@Artelius:实际上,Windows(至少从Win2K开始)确实支持连接点(en.wikipedia.org/wiki/NTFS_junction_point),而Vista开始支持NT符号链接(en.wikipedia.org/wiki/NTFS_symbolic_link)。无论如何,尽管符号链接可以帮助使更长/嵌套的路径更友好,但是我不认为如果达到路径长度限制,符号链接将如何帮助您。
Ashutosh Mehra

8
即使不存在此限制,也总是存在许多其他限制,并且每个限制有时都会令人讨厌。关键是为什么这个限制这么低?在8.3时代之后,使用兆/千兆大小的硬件,路径现在应该是一个动态分配的字符串,几乎没有大小限制。
罗兰2014年

12
微软10构建14352.最终解决这一问题,在Windows
沃伦P

3
是的,看起来您必须修改应用清单以使其具有长路径意识。
沃伦·P

3
@PatrickSzalapski不幸的是,它是固定的visualstudio.uservoice.com/forums/121579-visual-studio/…–
phuclv

Answers:


230

引用本文https://docs.microsoft.com/zh-cn/windows/desktop/FileIO/naming-a-file#maximum-path-length-limitation

最大路径长度限制

在Windows API(以下段落讨论了一些例外)中,路径的最大长度为MAX_PATH,它定义为260个字符。本地路径按以下顺序构造:驱动器号,冒号,反斜杠,由反斜杠分隔的名称组件以及终止的空字符。例如,驱动器D上的最大路径是“ D:\ 256个字符的字符串 <NUL>”,其中“ <NUL>”代表当前系统代码页的不可见终止空字符。(此处使用字符<>是为了清晰起见,并且不能成为有效路径字符串的一部分。)

现在我们看到它是1 + 2 + 256 + 1或[drive] [:\] [path] [null] =260。从DOS天开始,我们可以假定256是合理的固定字符串长度。回到DOS API,我们意识到系统跟踪每个驱动器的当前路径,并且我们有26个(带有符号的32个)最大驱动器(和当前目录)。

INT 0x21 AH = 0x47表示“此函数返回路径说明,不包含驱动器号和初始反斜杠。” 因此,我们看到系统将CWD存储为一对(驱动器,路径),并且您通过指定驱动器(1 = A,2 = B,...)来请求路径,如果您指定0,则假定该路径为INT 0x21 AH = 0x15 AL = 0x19返回的驱动器。现在我们知道为什么是260,而不是256,因为这4个字节没有存储在路径字符串中。

为什么要使用256字节的路径字符串,因为640K足够的RAM。


21
Windows API限制了长度,即使在最新的OS中也是如此。如果要改变这种现状,Microsoft担心会破坏今天使用的数亿个操作系统,因为它们再也没有像1980年代和1990年代那样了解内在和外在的天才了。风险不值得改变。 serverfault.com/questions/163419/...
马盖先

77
@MacGyver抱歉,这完全是胡说八道。Microsoft不想破坏数以百万计的编写质量差的应用程序,这些应用程序假设系统中从未得到保证的事情。不幸的是,很长一段时间以来事情都是一样的,以至于开发人员开始依赖它们,因此现在对其进行更改将破坏第三方应用程序,而MS也将受到指责。
2014年

25
顺便说一句,没有证据表明盖茨曾说过“ 640K Ram对每个人都足够” computerworld.com/article/2534312
Patrick Favre 2014年

11
@Basic Windows 保证了260个字符的限制。该常量被声明为一个常量,在Windows头文件中声明了仅可容纳260个字符的结构。无法更改它。
伊恩·博伊德

35
@Basic常数一旦编译到我的应用程序中就不会改变。我运行的应用程序最后一次构建于1994年,今天仍然可以在Windows 10中运行。Microsoft承诺一定的二进制大小的内存块,程序员遵循该规则。如果Microsoft更改常数,那么正确遵循编程API的每个现有应用程序都将损坏。您不能破坏二进制兼容性。
伊恩·博伊德

150

由于NTFS文件系统最多支持32k个字符的路径,因此这并非严格如此。您可以使用win32 api和“ \\?\”作为路径前缀,以使用超过260个字符。

.Net BCL团队博客的详细解释。
一小段摘录突出了长途问题

另一个令人担忧的问题是,由于暴露长途支持而导致的行为不一致。具有\\?\前缀的长路径可以在大多数与文件相关的Windows API中使用,但不能在所有Windows API中使用。例如,如果文件名长于MAX_PATH,则将模块映射到调用进程地址的LoadLibrary失败。因此,这意味着MoveFile将使您可以将DLL移到其路径长于260个字符的位置,但是当您尝试加载DLL时,它将失败。整个Windows API中都有类似的示例。存在一些变通办法,但它们是逐案的。


4
足够公平,但是这意味着您必须在很多地方使用P / Invoke,在我看来,这降低了.Net代码的可移植性。如果我想保持Mono兼容性怎么办?
杰弗里·卡梅隆

1
我的观点是,如果您确实愿意,可以使用长路径。但是我同意这很痛苦,我个人也避免这种情况。
softveda

5
这应该是选择的答案。实际上回答了由用户提出的问题,为什么存在此限制并提供了解决方法。支持可见性
KyleMit

2
在我看来,Microsoft需要修复其API,我想这不是优先事项。我很惊讶Windows 8中仍然存在该限制
。– Mas

3
@Mas想要的“修复”在Windows XP之前就完成了。调用其API的unicode版本将允许您访问“扩展路径”。我相信资源管理器会自动处理此问题。这是一种支持它的功能-msdn.microsoft.com/zh-cn/library/windows/desktop/…
Natalie Adams

108

问题是为什么限制仍然存在。当然,现代Windows可以增加它的侧面,MAX_PATH以允许更长的路径。为什么没有取消限制?

  • 无法删除它的原因是Windows承诺永远不会更改。

通过API合同,Windows已保证所有应用程序标准文件API绝不会返回比260字符更长的路径。

考虑以下正确的代码:

WIN32_FIND_DATA findData;

FindFirstFile("C:\Contoso\*", ref findData);

Windows向我的程序保证它将填充我的WIN32_FIND_DATA结构:

WIN32_FIND_DATA {
   DWORD    dwFileAttributes;
   FILETIME ftCreationTime;
   FILETIME ftLastAccessTime;
   FILETIME ftLastWriteTime;
   //...
   TCHAR    cFileName[MAX_PATH];
   //..
}

我的应用程序未声明常量的值MAX_PATH,而Windows API则声明了。我的应用程序使用了该定义的值。

我的结构已正确定义,并且仅分配592总字节数。这意味着我只能接收少于260字符的文件名。Windows 保证,如果我正确编写了应用程序,则将来我的应用程序将继续运行。

如果Windows允许文件名长于260字符,则我的现有应用程序(正确使用正确的API)将失败。

对于要求Microsoft更改MAX_PATH常量的任何人,他们首先需要确保没有现有的应用程序失败。例如,我仍然拥有并使用经编写可在Windows 3.11上运行的Windows应用程序。它仍然可以在64位Windows 10上运行。这就是向后兼容的优势。

微软确实创造了一种使用完整的32,768个路径名的方法。但是他们必须创建一个新的API合同才能做到这一点。首先,您应该使用Shell API枚举文件(因为并非所有文件都存在于硬盘驱动器或网络共享中)。

但是它们也不必破坏现有的用户应用程序。绝大多数应用程序使用shell api进行文件工作。每个人都打电话给FindFirstFile/ FindNextFile并每天打电话。


4
@JosiahKeller如果这样做,它将破坏最初为该方法定义的协定,并且这样做可能会覆盖意外的内存,并可能会打开一个安全漏洞。解决此问题的唯一方法是提供一个新的改进的API(例如Unicode感知变体),并希望每个人都使用较新的API重新编译/重新发布其所有应用程序。
罗兰·肖

2
@Ryios我认为现有的Windows应用程序不能在Linux上运行。
伊恩·博伊德

9
向后兼容性很好。但是我认为今天避免出现此类(通常是非常讨厌的)问题比支持Windows 3.1应用程序更为重要。有多少人遇到长途跋涉的问题?还有多少人仍在使用Windows 3.1应用程序?他们甚至取消了对Windows XP的支持。那么,为什么他们不做一个声明,即Windows [x]和更高版本的应用程序假定路径的长度不能超过260个字符,那么当他们计算一个较长的路径时却无法按预期工作呢?我们的速度限制也不考虑马车。
JuSchu

2
@JuSchu不仅仅是Windows 3.1应用程序。今天使用正确的API编写的应用程序将无法运行。
伊恩·博伊德


62

在Windows 10中,您可以通过修改注册表项来消除限制

提示 从Windows 10版本1607开始,MAX_PATH限制已从常见的Win32文件和目录功能中删除。但是,您必须选择加入新行为。

注册表项允许您启用或禁用新的长路径行为。要启用长路径行为,请将注册表项设置为HKLM\SYSTEM\CurrentControlSet\Control\FileSystem LongPathsEnabled(Type:)REG_DWORD。第一次调用受影响的Win32文件或目录函数(列表如下)后,键值将由系统缓存(按进程)。在该过程的生存期内,将不会重新加载注册表项。为了使系统上的所有应用都能识别密钥的值,可能需要重新启动,因为在设置密钥之前可能已经启动了某些进程。注册表项还可以通过位于的组策略来控制Computer Configuration > Administrative Templates > System > Filesystem > Enable NTFS long paths。您还可以通过清单来为每个应用启用新的长路径行为:

<application xmlns="urn:schemas-microsoft-com:asm.v3">
    <windowsSettings xmlns:ws2="http://schemas.microsoft.com/SMI/2016/WindowsSettings">
        <ws2:longPathAware>true</ws2:longPathAware>
    </windowsSettings>
</application>

15
令人遗憾的是,即使在最新版本的Win10中,文件资源管理器本身在处理长路径名时仍然存在问题。甚至上下文菜单中的“复制为路径”也无法按预期工作;它只复制前260个字符。您无法创建文件夹,无法复制/移动/打开文件...让我想知道此更改的意义是什么。
raymai97

请注意,声称系统设置独立于清单设置的说法是错误的。两者都是必需的。必须在系统级别启用该策略,清单必须声明该应用程序支持长路径。
Eryk Sun

我读到,进行此更改可能会导致与较旧的32位应用程序发生兼容性问题,但是这种类型的兼容性问题是否很常见?我想自己进行更改。lifehacker.com/...
KDP

32

您可以将文件夹安装为驱动器。在命令行中,如果有路径,则可以使用以下命令C:\path\to\long\folder将其映射到驱动器号X:

subst x: \path\to\long\folder

尝试执行此命令时,我收到“无效的参数j:”
barrypicker 2013年

这需要从管理员(高架)命令提示符下运行。
Mrchief 2014年

使用正斜杠将失败,需要使用反斜杠。
cchamberlain 2015年

1
我不确定这是否仅适用于Windows 10,但是我只是发现,当尝试运行此命令时,如果按照上述建议以管理员身份运行,则该驱动器似乎不可用。这是因为该行为似乎类似于映射网络驱动器,并且是特定于会话的,所以当我以管理员身份运行并使用此命令时,该会话可以使用x:TL; DR如果看不到驱动器尝试在没有管理员模式的情况下运行命令。
Jaddie

subst是本地会话/帐户- 有关如何使其“系统级”的信息,请参见superuser.com/questions/29072/…–
user2864740

18

解决路径限制的一种方法是缩短具有符号链接的路径条目。

例如:

  1. 创建C:\p目录以保留指向长路径的短链接
  2. mklink /J C:\p\foo C:\Some\Crazy\Long\Path\foo
  3. 添加C:\p\foo到您的路径而不是长路径

3
不必首先创建目录,因此步骤1是不必要的。
ohaal 2015年

2
这种技巧并不总是可行,因为许多应用程序尝试解析链接
nponeccop

/j选项为本地卷设备或本地卷上的路径(例如Unix绑定安装)创建结点安装点。它不会创建符号链接。这是一个重要的区别,因为结点挂载点始终在服务器上评估,并且必须以本地设备为目标,而符号链接是在客户端上评估的,并且可以以远程路径为目标(如果策略允许)。类似于subst.exe驱动器(即DefineDosDeviceW),结点目标通常限于大约4K个字符。它实际上是8K个字符,在替换路径和显示路径之间平均分配。
Eryk Sun

12

您可以使用PowerShell启用长路径名:

Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem' -Name LongPathsEnabled -Type DWord -Value 1 

另一个版本是在Computer Configuration/ Administrative Templates/ System/中使用组策略Filesystem

组策略编辑器


2
每个应用程序仍然必须声明它是长路径感知的。微软通过使应用程序清单看起来像是启用此功能的另一种方式,在传达此信息方面做得很差,而不是清楚地说明这是操作系统(系统级策略)和应用程序之间必须达成共识的合同。
Eryk Sun

8

至于为什么它仍然存在-MS并不认为它是优先事项,并且相对于升级其OS(至少在这种情况下),重视向后兼容性。

我使用的一种解决方法是对路径中的目录使用“短名称”,而不是其标准的,人类可读的版本。因此,例如,对于C:\Program Files\我将使用,C:\PROGRA~1\ 您可以使用来找到短名称的等效项dir /x


1
可以在注册表中禁用短路径名(或者是文件系统本身吗?),因此这并不是一个可靠的解决方法。
rubenvb

3
@rubenvb我敢肯定,如果不是所有Windows功能可以在注册表被禁用,因此¯\ _(ツ)_ /¯
康拉德

可以为整个系统或每个卷禁用NTFS的短名称生成(这应该是因为它在许多情况下效率低下),因此即使对于系统驱动器上的路径(必须为NTFS),这也是一种不可靠的方法。可以在NTFS中的文件和目录上手动设置短名称,但这不会扩展到根本不支持短名称的较新文件系统,例如exFAT和ReFS。短名称应被视为不推荐使用的功能,保留该功能是为了在有限的情况下保持兼容性,例如使用单字节和双字节代码页的旧ANSI / OEM API。
Eryk Sun

@eryksun请参阅我之前有关禁用短路径名的评论。:)仅仅因为您认为它应该被弃用,并不意味着它实际上是不推荐的。MS没有计划弃用此功能。(而且,为什么要在exFAT / ReFS分区上安装Windows软件?)
康拉德(Conrad

我仍然说只使用非规范化的设备路径(即“ \\?\”前缀),因为它们始终可用并且很明显。例如,翻译PATH并将其传递给SearchPathW。这也是有效的,因为运行时库无论如何都会为NT创建“ \\?\”设备路径。对于较新的文件系统,除便携式应用程序外,我们可能不会在exFAT卷上看到安装的软件,因为它没有安全性,但我不排除ReFS。出于方便,空间或性能的考虑,用户将程序安装在非标准位置。
Eryk Sun

7

至于如何应对Windows上的路径大小限制-使用7zip打包(和解压缩)您的路径长度敏感文件似乎是一个可行的解决方法。我用它来传输多个IDE安装程序(那些Eclipse插件路径,yikes!)和成堆的自动生成的文档,到目前为止,还没有一个单一的问题。

不太确定它如何规避Windows设置的260个字符限制(从技术PoV),但是嘿,它起作用了!

有关其SourceForge页面的更多详细信息,请点击此处

“ NTFS实际上可以支持最多32,000个字符的路径名。”

7-zip也支持这种长名称。

但是在SFX代码中已将其禁用。一些用户不喜欢漫长的道路,因为他们不了解如何使用它们。这就是为什么我在SFX代码中禁用了它。

发行说明

9.32 alpha 2013-12-01

  • 改进了对长度超过260个字符的文件路径名的支持。

4.44 beta 2007年1月20日

  • 7-Zip现在支持超过260个字符的文件路径名。

重要说明:为了使其正常工作,您需要直接在7zip “提取”对话框中指定目标路径,而不是将文件拖放到预期的文件夹中。否则,“临时”文件夹将用作临时缓存,一旦Windows资源管理器开始将文件移至其“最终放置位置”,您将跳回相同的260个字符限制。有关更多信息,请参见对此问题的答复。


3
我错了,7zip和WinRAR确实提取了所有文件夹和文件。只是Windows中文件夹的属性仅报告不违反限制的文件夹和文件的数量。好像到达最大路径时,Windows资源管理器不会更深入地发现文件夹。
Twisted Whisper 2015年

它可以删除在7-ZIP与移德尔长路径。
Laurie Stearn

简短的答案-使用7zip解压缩.zip文件。...在Windows 7上为我工作
andrewcockerham


2

解决该问题的另一种方法是使用Cygwin,这取决于您要对文件执行的操作(即Cygwin命令是否满足您的需求)

例如,它允许复制,移动或重命名甚至Windows资源管理器也无法访问的文件。或者当然处理它们的内容,例如md5sum,grep,gzip等。

同样对于您正在编码的程序,您可以将它们链接到Cygwin DLL,这将使它们能够使用长路径(尽管我尚未对此进行测试)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.