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

为什么Windows中存在260个字符的路径长度限制?,windows,path,limit,Windows,Path,Limit,我曾在不恰当的时候遇到过几次这个问题: 尝试在具有深度路径的开源Java项目上工作 在源代码管理中存储deep Fitnesse wiki树 尝试使用Bazaar导入我的源代码管理树时出错 为什么会有这样的限制 为什么它还没有被移除 你如何应对路径限制? 不,切换到Linux或Mac OS X不是这个问题的有效答案;) 引用这篇文章 最大路径长度限制 在Windows API中(以下段落讨论了一些例外情况),路径的最大长度为MAX_path,定义为260个字符。本地路径按以下顺序构造:驱动器

我曾在不恰当的时候遇到过几次这个问题:

  • 尝试在具有深度路径的开源Java项目上工作
  • 在源代码管理中存储deep Fitnesse wiki树
  • 尝试使用Bazaar导入我的源代码管理树时出错
为什么会有这样的限制

为什么它还没有被移除

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

引用这篇文章

最大路径长度限制

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

现在我们看到它是1+2+256+1或[drive][:\][path][null]=260。可以假设256是DOS时代的合理固定字符串长度。回到DOSAPI,我们意识到系统跟踪每个驱动器的当前路径,我们有(和当前目录)

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中的长路径。
一个小摘录突出了这一问题的长途跋涉

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


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

subst x: \path\to\long\folder

处理路径限制的一种方法是使用符号链接缩短路径条目

例如:

  • 创建
    C:\p
    目录以保留指向长路径的短链接
  • mklink/jc:\p\foo C:\Some\Crazy\Long\Path\foo
  • C:\p\foo
    添加到您的路径,而不是长路径
  • 至于为什么仍然存在——MS不认为它是优先考虑的,并且在推进OS(至少在这种情况下)时考虑向后兼容性。


    我使用的一种解决方法是对路径中的目录使用“短名称”,而不是它们的标准、人类可读版本。例如,对于
    C:\Program Files\
    我会使用
    C:\PROGRA~1\
    你可以使用
    dir/x
    找到短名称等价物,问题是为什么这个限制仍然存在。当然,现代Windows可以增加
    MAX_PATH
    的侧面,以允许更长的路径。为什么没有取消限制

    • 无法删除它的原因是Windows承诺它永远不会更改
    通过API合同,Windows向所有应用程序保证,标准文件API返回的路径永远不会超过
    260
    个字符

    考虑以下正确的代码:

    WIN32_FIND_DATA findData;
    
    FindFirstFile("C:\Contoso\*", ref findData);
    
    Windows保证我的程序将填充我的
    WIN32_FIND_数据
    结构:

    WIN32_FIND_DATA {
       DWORD    dwFileAttributes;
       FILETIME ftCreationTime;
       FILETIME ftLastAccessTime;
       FILETIME ftLastWriteTime;
       //...
       TCHAR    cFileName[MAX_PATH];
       //..
    }
    
    我的应用程序没有声明常量
    MAX\u PATH
    的值,Windows API声明了。我的应用程序使用了定义的值

    我的结构定义正确,只分配了总共592个字节。这意味着我只能接收少于260个字符的文件名。Windows向我承诺,如果我正确编写应用程序,我的应用程序将在将来继续工作

    如果Windows允许文件名长度超过260个字符,那么我现有的应用程序(正确使用了正确的API)将失败

    对于要求Microsoft更改
    MAX_PATH
    常量的任何人,他们首先需要确保没有现有应用程序出现故障。例如,我仍然拥有并使用一个为在Windows3.11上运行而编写的Windows应用程序。它仍然在64位Windows10上运行。这就是向后兼容性带给你的

    Microsoft确实创建了一种使用完整32768路径名的方法;但他们必须创建一个新的API合同来实现这一点。首先,您应该使用Shell API枚举文件(因为并非所有文件都存在于硬盘驱动器或网络共享上)

    但它们也不能破坏现有的用户应用程序。绝大多数应用程序不使用shell api f
    <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>
    
    [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem]
    "LongPathsEnabled"=dword:00000001