为什么Windows中存在260个字符的路径长度限制?
在不合时宜的情况下,我曾经遇到过几次这样的问题:
- 试图在深度路径上开源的Java项目
- 在源代码控制中存储深度的Fitnesse维基树
- 尝试使用Bazaar导入我的源代码控制树的错误
为什么这个限制存在?
为什么它还没有被删除?
你如何应对路径限制? …不,切换到Linux或Mac OS X不是这个问题的有效答案;)
引用这篇文章http://msdn.microsoft.com/en-us/library/aa365247(VS.85).aspx#maxpath
最大路径长度限制
在Windows API(以下段落中讨论一些例外)中,路径的最大长度是MAX_PATH ,定义为260个字符。 本地路径按以下顺序组织:驱动器号,冒号,反斜杠,用反斜杠分隔的名称组件以及终止的空字符。 例如,驱动器D上的最大路径为“D:\ 一些256个字符的路径字符串 <NUL>”,其中“<NUL>”表示当前系统代码页的不可见的终止空字符。 (字符<>在这里用于视觉清晰,不能是有效路径字符串的一部分。)
现在我们看到它是1 + 2 + 256 + 1或[驱动器] [:\] [路径] [空] = 260。人们可以假设256是一个合理的固定字符串长度从DOS天。 回到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。
这是不正确的,因为NTFS文件系统支持多达32k个字符的路径。 您可以使用win32 api和前缀“ \\?\
”来使用大于260个字符的路径。
.Net BCL团队博客的详细解释。
一小段摘录突出了长路径的问题
另一个问题是暴露长途支持导致的行为不一致。 带有
\\?\
前缀的长路径可用于大多数与文件相关的Windows API,但不能用于所有的Windows API。 例如,如果文件名比MAX_PATH长,将模块映射到调用进程地址的LoadLibrary失败。 所以这意味着MoveFile将让你移动一个DLL到一个位置,使得它的路径长度超过260个字符,但是当你试图加载DLL时,它会失败。 整个Windows API都有类似的例子。 一些解决方法存在,但他们是在个案的基础上。
问题是为什么限制仍然存在。 当然,现代Windows可以增加MAX_PATH
的一面以允许更长的路径。 为什么限制没有被删除?
- 它不能被删除的原因是Windows承诺永远不会改变。
通过API合约,Windows已经保证所有的应用程序标准文件API永远不会返回超过260
字符的路径。
考虑以下正确的代码:
WIN32_FIND_DATA findData; FindFileFirst("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
并在一天内调用它。
您可以将文件夹安装为驱动器。 从命令行,如果你有一个路径C:\path\to\long\folder
你可以把它映射到驱动器号X:
using:
subst x: \path\to\long\folder
从Windows 10.您可以通过修改注册表项来删除限制 。
提示从Windows 10版本1607开始,MAX_PATH限制已从常见的Win32文件和目录函数中删除。 但是,您必须选择新的行为。
注册表项允许您启用或禁用新的长路径行为。 要启用长路径行为,请在
HKLM\SYSTEM\CurrentControlSet\Control\FileSystem LongPathsEnabled
(类型: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>
处理路径限制的一种方法是使用符号链接来缩短路径条目。
例如:
- 创建一个
C:\p
目录来保持较长的路径的短链接 -
mklink /JC:\p\foo C:\Some\Crazy\Long\Path\foo
- 将
C:\p\foo
添加到您的路径而不是长路径
至于为什么这仍然存在 – MS不认为它是一个优先事项,并且在推进他们的操作系统(至少在这种情况下)向后兼容。
我使用的解决方法是使用路径中目录的“简称”,而不是标准的,人类可读的版本。 因此, 例如对于C:\Program Files\
我将使用C:\PROGRA~1\
您可以使用dir /x
找到短名称等价物。
至于如何应对Windows上的路径大小限制 – 使用7zip打包( 和解压缩)您的路径长度敏感的文件似乎是一个可行的解决方法。 我用它来传输几个IDE安装(这些Eclipse插件路径,yike!)和一堆自动生成的文档,到目前为止还没有一个单一的问题。
真的不知道它是如何逃避Windows设置的260个字符限制(从技术PoV),但嘿,它的工作原理!
有关SourceForge页面的更多详细信息,请访问 :
“NTFS实际上可以支持长达32,000个字符的路径。”
7-zip也支持这么长的名字。
但在SFX代码中禁用。 有些用户不喜欢漫长的路径,因为他们不知道如何使用它们。 这就是为什么我已经禁用它在SFX代码。
并发布说明 :
9.32阿尔法2013-12-01
- 改进了对超过260个字符的文件路径名称的支持。
4.44测试版2007-01-20
- 7-Zip现在支持超过260个字符的文件路径名。
重要提示:为使其正常工作,您需要直接在7zip “提取”对话框中指定目标路径,而不是将文件拖放到目标文件夹中。 否则,“Temp”文件夹将被用作临时缓存,一旦Windows资源管理器开始将文件移动到“最终安放地点”,您将弹出相同的260个字符限制。 请参阅对这个问题的答复以获取更多信息。