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


尝试在具有深路径的开源Java项目上工作br />尝试使用Bazaar导入我的源代码控制树时发生错误

为什么存在此限制?

为什么还没有删除它?

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

评论

@Artelius:实际上,Windows(至少从Win2K起)确实支持连接点(en.wikipedia.org/wiki/NTFS_junction_point),而Vista则支持NT符号链接(en.wikipedia.org/wiki/NTFS_symbolic_link)。无论如何,尽管符号链接可以帮助使更长/嵌套的路径更友好,但是我不认为如果遇到路径长度限制,符号链接将有何帮助。
即使不存在此限制,也总是存在许多其他限制,并且每个限制有时都会令人讨厌。关键是为什么这个限制这么低?在8.3时代之后,并且使用兆/千兆大小的硬件,路径现在应该是动态分配的字符串,且大小实际上是无限的。
微软终于在Windows 10 Build 14352中解决了这个问题。

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

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

#1 楼

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


最大路径长度限制

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


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

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

评论


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

– MacGyver
2014年7月16日在21:40



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

–基本
2014年8月28日在9:36

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

–帕特里克·法夫尔(Patrick Favre)
2014年11月26日15:34

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

–伊恩·博伊德(Ian Boyd)
15年7月20日在13:59

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

–伊恩·博伊德(Ian Boyd)
15年7月21日在14:12

#2 楼

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

.Net BCL团队博客中关于长途路径的详细说明。
一小段摘录突出了长途路径的问题


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


评论


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

–杰弗里·卡梅隆(Jeffrey Cameron)
09年12月10日在22:50

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

– softveda
09年12月11日在2:12

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

– KyleMit
13年3月20日在21:06

在我看来,Microsoft需要修复其API,我想这不是优先事项。我对Windows 8中仍然存在此限制感到惊讶。

–马斯
13年5月15日在15:16

@Mas所需的“修复”已全部完成,直到Windows XP。调用其API的unicode版本将允许您访问“扩展路径”。我相信资源管理器会自动处理此问题。这是一个支持它的功能-msdn.microsoft.com/zh-cn/library/windows/desktop/…。

–娜塔莉·亚当斯(Natalie Adams)
13-10-16在3:59

#3 楼

问题是为什么限制仍然存在。当然,现代Windows可以增加MAX_PATH的宽度,以允许更长的路径。为什么未删除该限制?


无法删除该限制的原因是Windows承诺它永远不会改变。

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

请考虑以下正确代码:我的程序将填充我的WIN32_FIND_DATA结构:

WIN32_FIND_DATA findData;

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


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

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

如果Windows允许文件名长于260字符,那么我现有的应用程序(正确使用了正确的API)将失败。常量,他们首先需要确保没有现有的应用程序失败。例如,我仍然拥有并使用被编写为在Windows 3.11上运行的Windows应用程序。它仍然可以在64位Windows 10上运行。这就是向后兼容的原因。Microsoft确实创造了一种使用完整32,768个路径名的方法。但他们必须创建一个新的API合同才能做到这一点。首先,您应该使用Shell API枚举文件(因为并非所有文件都存在于硬盘驱动器或网络共享上)。

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

评论


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

–Rowland Shaw
2015年10月19日在11:22

微软只需要抓紧时间,使那里的Linux发行版...我将立即切换并使用旧的Windows API。

–瑞安·曼(Ryan Mann)
15年11月21日在19:15

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

– JuSchu
16年6月12日在18:36

@TheincredibleJan MSDN。文档创建合同,这就是为什么您需要非常小心文档的原因。

–伊恩·博伊德(Ian Boyd)
17年5月10日在15:01



@КонстантинВан使用该解决方案,调用者需要在调用函数之前知道为FIND_DATA结构分配多少内存?这对代码大小不利。现在,一个函数调用变为两个,在查找所有文件的循环中,我使所有操作的速度降低了50%。在我的4.77MHz机器上,这不好。您让事情变慢了50%。我必须每次都调用此函数,并每次都重新分配内存?不好大概在hte结构的末尾会有这个可变长度的数组,其他大小我必须做数学运算才能读取后续字段。

–伊恩·博伊德(Ian Boyd)
19年1月10日在20:21

#4 楼

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


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

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

<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>



评论


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

–raymai97
17年6月29日在7:43

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

–太阳神
19年8月2日在11:33

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

– KDP
2月7日下午14:44

@KDP,它会与大多数32位程序,许多64位程序以及其他无法处理更长文件名的设备(即,您将无法将文件传输到/来自大多数存储卡,闪存驱动器,媒体服务器/ NAS,路由器,旧计算机,打印机等)

– Synetech
9月15日下午1:26

#5 楼

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

subst x: \path\to\long\folder


评论


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

–berrypicker
13年8月9日在18:53

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

– r
2014年6月27日14:46

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

–cchamberlain
15年5月22日在22:36

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

–贾迪
15年9月14日在18:48

替代品是本地会话/帐户-有关如何使其“系统范围内”的信息,请参见superuser.com/questions/29072/…

–user2864740
19年3月1日19:23



#6 楼

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

例如:


创建一个C:\p目录以将短链接保持为长链接路径
mklink /J C:\p\foo C:\Some\Crazy\Long\Path\foo
C:\p\foo添加到您的路径而不是长路径


评论


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

–ohaal
15年2月18日在13:34

由于许多应用程序尝试解析链接,因此此技巧并不总是有效

– nponeccop
18年1月3日在19:54

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

–太阳神
19年8月2日,11:57

#7 楼

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

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


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



评论


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

–太阳神
19年8月2日在12:09

不幸的是,即使是Visual Studio 2019社区也不支持长路径

– Pieterjan
9月26日22:23



#8 楼

至于为什么它仍然存在-MS并不认为它是优先事项,并且在升级其OS之前(至少在这种情况下)重视向后兼容性。路径中目录的名称”,而不是其标准的人类可读版本。所以对于C:\Program Files\,我将使用C:\PROGRA~1\。您可以使用dir /x找到短名称的等效项。

评论


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

– rubenvb
17年2月2日于13:03

@rubenvb我敢肯定,即使不是Windows的所有功能,大多数也可以在注册表中禁用,所以\\(ツ)_ /¯

–康拉德
17 Dec 2'在20:02



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

–太阳神
19年8月2日在12:05

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

–康拉德
19年8月2日在16:00



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

–太阳神
19年8月2日在18:05

#9 楼

至于如何应对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-01-20


7 -Zip现在支持长度超过260个字符的文件路径名。 ”对话框,而不是将文件拖放到预期的文件夹中。否则,“临时”文件夹将用作临时缓存,一旦Windows资源管理器开始将文件移至其“最终放置位置”,您将跳回相同的260个字符限制。有关更多信息,请参见对此问题的答复。

评论


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

–扭曲的耳语
2015年10月1日于17:57

使用shift-del可以删除7-zip中的长路径。

– Laurie Stearn
16年5月4日在11:51

简短答案-使用7zip解压缩.zip文件。...在Windows 7上对我有用

– andrewcockerham
16 Dec 2'在3:05

#10 楼

确实如此,并且由于某种原因它是默认值,但是您可以使用此注册表项轻松地覆盖它: microsoft.com/jeremykuhne/2016/07/30/net-4-6-2-and-long-paths-on-windows-10/

#11 楼

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

例如,它允许复制,移动或重命名文件Windows资源管理器也无法做到。当然也可以处理它们的内容,例如md5sum,grep,gzip等。路径(不过我还没有测试过)