我有几次在不合时宜的时候遇到过这个问题:
尝试在具有深度路径的开源Java项目上工作 在源代码控制中存储深度fitness wiki树 试图使用Bazaar导入源代码控制树时出错
为什么会有这个限制?
为什么它还没有被移除?
您如何应对路径限制? 不,切换到Linux或Mac OS X并不是这个问题的有效答案;)
我有几次在不合时宜的时候遇到过这个问题:
尝试在具有深度路径的开源Java项目上工作 在源代码控制中存储深度fitness wiki树 试图使用Bazaar导入源代码控制树时出错
为什么会有这个限制?
为什么它还没有被移除?
您如何应对路径限制? 不,切换到Linux或Mac OS X并不是这个问题的有效答案;)
引用这篇文章https://learn.microsoft.com/en-us/windows/desktop/FileIO/naming-a-file#maximum-path-length-limitation
Maximum Path Length Limitation In the Windows API (with some exceptions discussed in the following paragraphs), the maximum length for a path is MAX_PATH, which is defined as 260 characters. A local path is structured in the following order: drive letter, colon, backslash, name components separated by backslashes, and a terminating null character. For example, the maximum path on drive D is "D:\some 256-character path string<NUL>" where "<NUL>" represents the invisible terminating null character for the current system codepage. (The characters < > are used here for visual clarity and cannot be part of a valid path string.)
现在我们看到它是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的内存足够了。
这并不是严格意义上的,因为NTFS文件系统支持最多32k个字符的路径。你可以使用win32 api和“\\?”使用大于260个字符作为路径前缀。
. net BCL团队博客中关于漫长路径的详细解释。 一个小节选强调了长路径的问题
Another concern is inconsistent behavior that would result by exposing long path support. Long paths with the \\?\ prefix can be used in most of the file-related Windows APIs, but not all Windows APIs. For example, LoadLibrary, which maps a module into the address of the calling process, fails if the file name is longer than MAX_PATH. So this means MoveFile will let you move a DLL to a location such that its path is longer than 260 characters, but when you try to load the DLL, it would fail. There are similar examples throughout the Windows APIs; some workarounds exist, but they are on a case-by-case basis.
您可以将文件夹作为驱动器挂载。从命令行,如果你有一个路径C:\path\to\long\文件夹,你可以将它映射到驱动器号X:使用:
subst x: \path\to\long\folder
处理路径限制的一种方法是使用符号链接缩短路径条目。
例如:
创建一个C:\p目录,将短链接保存到长路径 mklink /J C:\p\foo C:\一些\疯狂\长\路径\foo 将C:\p\foo添加到您的路径中,而不是长路径
至于为什么这个问题仍然存在——微软并不认为它是一个优先级,并且认为向后兼容性比改进他们的操作系统更重要(至少在这种情况下)。
我使用的一种变通方法是为路径中的目录使用“短名称”,而不是使用标准的、人类可读的版本。例如,对于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_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,并称之为一天。
至于如何应对Windows上的路径大小限制,使用7zip来打包(和解包)路径长度敏感的文件似乎是一个可行的解决方案。我已经使用它传输了几个IDE安装(那些Eclipse插件路径,哎呀!)和大量自动生成的文档,到目前为止还没有遇到任何问题。
不知道它是如何逃避260字符限制设置由Windows(从技术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个字符的文件路径名。
重要提示:为了使其正常工作,你需要直接在7zip“Extract”对话框中指定目标路径,而不是将文件拖放到预期的文件夹中。否则,“Temp”文件夹将被用作临时缓存,一旦Windows资源管理器开始将文件移动到“最终休息位置”,你就会陷入同样的260个字符限制。有关更多信息,请参阅对该问题的答复。
从Windows 10。可以通过修改注册表项来消除限制。
Tip Starting in Windows 10, version 1607, MAX_PATH limitations have been removed from common Win32 file and directory functions. However, you must opt-in to the new behavior. A registry key allows you to enable or disable the new long path behavior. To enable long path behavior set the registry key at HKLM\SYSTEM\CurrentControlSet\Control\FileSystem LongPathsEnabled (Type: REG_DWORD). The key's value will be cached by the system (per process) after the first call to an affected Win32 file or directory function (list follows). The registry key will not be reloaded during the lifetime of the process. In order for all apps on the system to recognize the value of the key, a reboot might be required because some processes may have started before the key was set. The registry key can also be controlled via Group Policy at Computer Configuration > Administrative Templates > System > Filesystem > Enable NTFS long paths. You can also enable the new long path behavior per app via the manifest: <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>
另一种处理方法是使用Cygwin,这取决于您想对文件做什么(即Cygwin命令是否适合您的需要)
例如,它允许复制、移动或重命名连Windows资源管理器都做不到的文件。当然,也可以处理它们的内容,如md5sum、grep、gzip等。
此外,对于你正在编写的程序,你可以将它们链接到Cygwin DLL,这将使它们能够使用长路径(我还没有测试这个)
它确实如此,而且出于某种原因,它是默认的,但你可以很容易地用这个注册表项覆盖它:
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem]
"LongPathsEnabled"=dword:00000001
参见:https://blogs.msdn.microsoft.com/jeremykuhne/2016/07/30/net-4-6-2-and-long-paths-on-windows-10/
您可以使用PowerShell启用长路径名:
Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem' -Name LongPathsEnabled -Type DWord -Value 1
另一个版本是在计算机配置/管理模板/系统/文件系统中使用组策略: