ChatGPT解决这个技术问题 Extra ChatGPT

Why does the 260 character path length limit exist in Windows?

I have come up against this problem a few times at inopportune moments:

Trying to work on open source Java projects with deep paths

Storing deep Fitnesse wiki trees in source control

An error trying to use Bazaar to import my source control tree

Why does this limit exist?

Why hasn't it been removed yet?

How do you cope with the path limit? And no, switching to Linux or Mac OS X is not a valid answer to this question ;)

@Artelius: Actually, Windows (at least from Win2K onwards) does support junction points (en.wikipedia.org/wiki/NTFS_junction_point), and Vista onwards support NT Symbolic links (en.wikipedia.org/wiki/NTFS_symbolic_link). Anyway, while symlinks can help make longer/nested paths more friendly, I can't think how symlinks would help if you're hitting path length limits.
Even if this limit did not exist, there are always lots of other limits, and every one of them could be annoying at some point. The point is why is this limit so low? After the era of 8.3, and with mega/giga sized hardware, a path should now be a dynamically allocated string with a virtually unlimited size.
Microsoft is finally addressing this problem, in Windows 10 Build 14352.
Yes, and it looks like you have to modify the app manifest to make it long path aware.
@PatrickSzalapski unfortunately it was fixed visualstudio.uservoice.com/forums/121579-visual-studio/…

J
John Cummings

Quoting this article https://docs.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" where "" 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.)

Now we see that it is 1+2+256+1 or [drive][:\][path][null] = 260. One could assume that 256 is a reasonable fixed string length from the DOS days. And going back to the DOS APIs we realize that the system tracked the current path per drive, and we have 26 (32 with symbols) maximum drives (and current directories).

The INT 0x21 AH=0x47 says “This function returns the path description without the drive letter and the initial backslash.” So we see that the system stores the CWD as a pair (drive, path) and you ask for the path by specifying the drive (1=A, 2=B, …), if you specify a 0 then it assumes the path for the drive returned by INT 0x21 AH=0x15 AL=0x19. So now we know why it is 260 and not 256, because those 4 bytes are not stored in the path string.

Why a 256 byte path string, because 640K is enough RAM.


The Windows API limits the length, even in the latest OS. Microsoft is afraid to break hundreds of millions of operating systems in use today if this were to change because they don't have geniuses working for them anymore that understand the API inside and out, like they did in the 1980s and 1990s. The risk is not worth changing it. serverfault.com/questions/163419/…
@MacGyver Sorry, but that's utter nonsense. Microsoft doesn't want to break the millions of poorly written applications out there that assume things about the system that were never guaranteed. Unfortunately, things were the same way for so long that developers came to rely on them, so changing it now would break 3rd party applications and MS would get the blame.
btw there is no proof that Gates ever said the "640K Ram is enough for everyone" computerworld.com/article/2534312
@Basic The 260 character limit was guaranteed by Windows. The constant was declared as a constant, a structure was declared in the Windows header files that only has room for 260 characters. There is no way to change it.
@Basic The constant doesn't change once it's compiled into my application. I run an application which was last built in 1994, and still runs today in Windows 10. Microsoft promised a certain binary size of a block of memory, and the programmer followed that rule. If Microsoft were to change the constant, then every existing application, who correctly followed the programming API, would be broken. You cannot break binary compatibility.
d
dthorpe

This is not strictly true as the NTFS filesystem supports paths up to 32k characters. You can use the win32 api and "\\?\" prefix the path to use greater than 260 characters.

A detailed explanation of long path from the .Net BCL team blog.
A small excerpt highlights the issue with long paths

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.


Fair enough, but it means you have to use P/Invoke in a lot of places and this, to my mind, reduces the portability of your .Net code. What if I wanted to keep Mono-compatibility?
My point was that you can use long path if you really wanted to. But I agree that it is a pain and personally I would avoid this as well.
This should be the chosen answer. Actually answers the question posed by user of WHY this limit exists AND provides a work-around. Upvote for visibility
It sounds to me that Microsoft needs to fix their APIs, and I guess this is not a priority. I was surprised that this limit still exists in Windows 8.
@Mas The "fix" you want was done all the back to Windows XP. Calling the unicode version of their API will allow you to access the "extended path". I believe explorer automatically handles this. Here is one such function that supports it - msdn.microsoft.com/en-us/library/windows/desktop/… .
J
Jonathan Potter

The question is why does the limitation still exist. Surely modern Windows can increase the side of MAX_PATH to allow longer paths. Why has the limitation not been removed?

The reason it cannot be removed is that Windows promised it would never change.

Through API contract, Windows has guaranteed all applications that the standard file APIs will never return a path longer than 260 characters.

Consider the following correct code:

WIN32_FIND_DATA findData;

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

Windows guaranteed my program that it would populate my WIN32_FIND_DATA structure:

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

My application didn't declare the value of the constant MAX_PATH, the Windows API did. My application used that defined value.

My structure is correctly defined, and only allocates 592 bytes total. That means that i am only able to receive a filename that is less than 260 characters. Windows promised me that if i wrote my application correctly, my application would continue to work in the future.

If Windows were to allow filenames longer than 260 characters then my existing application (which used the correct API correctly) would fail.

For anyone calling for Microsoft to change the MAX_PATH constant, they first need to ensure that no existing application fails. For example, i still own and use a Windows application that was written to run on Windows 3.11. It still runs on 64-bit Windows 10. That is what backwards compatibility gets you.

Microsoft did create a way to use the full 32,768 path names; but they had to create a new API contract to do it. For one, you should use the Shell API to enumerate files (as not all files exist on a hard drive or network share).

But they also have to not break existing user applications. The vast majority of applications do not use the shell api for file work. Everyone just calls FindFirstFile/FindNextFile and calls it a day.


@JosiahKeller If it did, it would break the contract originally defined for that method, and doing that could overwrite unintended memory, and prtentially open a security hole. The only way to fix this is to offer a new improved API (like the Unicode aware variants), and hope everyone recompiles/rereleases all their applications using the newer API.
Backward compatibility is nice. But I think avoiding such (often really nasty) problems today is more important than supporting Windows 3.1 applications. How many people encounter problems with to long paths? And how many people do still use Windows 3.1 applications? They even canceld support for Windows XP. So why don't they just make an annoucement, that from Windows [x] and later applications which assume there won't be a path longer than 260 characters, will not work as expected when they ancounter a path which is to long? Our speed limits also don't regard carriages.
This answer confuses the max path component length, which is typically 255 characters for MS filesystems and completely fixed, with the max path length, which can be up to about 32,760 characters in NT due to the kernel's UNICODE_STRING structure. With the "\\?\" prefix, all of the common file systems such as NTFS, UDF, FAT32, and exFAT support the full NT max path length. The 260-character path limit is due to fixed buffers in the runtime library for DOS/Windows path processing (e.g. ANSI <=> Unicode, working directory, and DOS<=>NT path conversion).
@КонстантинВан With that solution the caller needs to know how much memory to allocate for the FIND_DATA structure before they can call the function? That's not good for code size. Now one function call becomes two, and in the loop of finding all files, i've just made everything 50% slower. On my 4.77MHz machine that's no good. You've made things 50% slower for nothing. And i have to call this every time, and reallocate memory every time? That's no good. Presumably you'd have this variable length array at the end of hte structure, othersize i have to do math to read the subsequent fields.
r
riQQ

From Windows 10. you can remove the limitation by modifying a registry key.

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


Sadly even in the latest version Win10, the File Explorer itself still has problem dealing with long path name. Even "Copy as Path" in the context menu doesn't work as expected; it only copy the first 260 chars. You can't create folder, copy/move/open file... Make me wonder what is the point of this change.
Note that the claim that the system setting is independent from the manifest setting is wrong. Both are required. The policy has to be enabled at the system level and the manifest has to declare that the application is long-path aware.
I read that making this change could cause compatibility issues with older 32-bit applications, but is this type of problem with compatibility common? I'd like to make the change myself. lifehacker.com/…
@KDP, it creates a compatibility problem with most 32-bit programs, a lot of 64-bit programs, and any other devices that aren't able to handle longer filenames (i.e., you wouldn't be able to transfer files to/from most memory-cards, flash-drives, media-servers/NAS, routers, older computers, printers, etc…)
@Synetech Things aren't that bad, because first of all the manifest controls if ONE concrete app is able to use longer paths or not at all. Second, to get a problem, you need longer paths for an app which doesn't support those anyway. It's pretty unlikely to have long, incompatible paths on some storage in the first place and AFTERWARDS using an incompatible app with those paths afterwards. Why should one do soß How did the files end up there at all etc.?
B
BaCaRoZzo

You can mount a folder as a drive. From the command line, if you have a path C:\path\to\long\folder you can map it to drive letter X: using:

subst x: \path\to\long\folder

i am receiving "Invalid paramter j:" when attempting this command
This needs to be run from an Administrator (elevated) command prompt.
This will fail with forward slashes, needs to be backslashes.
I am not sure if this applies to windows 10 only, however I just found that when trying to run this command, if I run as an administrator as suggested above the drive does not appear to be available. This is because the behaviour appears to be similar to mapping a network drive and is session specific etc, so when I ran as an administrator and used this command, that session could use x: TL;DR If you can't see the drive try running the command without being in administrator mode.
subst is local-session/account - see superuser.com/questions/29072/… for how to make it 'system wide'
B
BaCaRoZzo

One way to cope with the path limit is to shorten path entries with symbolic links.

For example:

create a C:\p directory to keep short links to long paths mklink /J C:\p\foo C:\Some\Crazy\Long\Path\foo add C:\p\foo to your path instead of the long path


Didn't have to create the directory first, so step 1 is not necessary.
This trick doesn't always work as many application try to resolve the links
The /j option creates a junction mountpoint for a local volume device or a path on a local volume (like a Unix bind mount). It does not create a symbolic link. It's an important distinction since junction mountpoints are always evaluated on a server and must target local devices, while symbolic links are evaluated on the client and may target remote paths (if allowed by policy). Like a subst.exe drive (i.e. DefineDosDeviceW), a junction target is typically limited to about 4K characters. It's actually 8K characters, split about evenly between the substitute path and the display path.
A Junction is a Hard Link. Junctions can only be made from the command line. There is no UI controls in the OS to create them. However, be aware of the dangers of using Hard Links as they can cause circular loops if someone tries to copy files that Hard Link back to their parent folder. I lost a hard drive once because someone created a Hard Link back to root so when someone recursively deleted a folder, it cycled back and deleted the whole hard drive.
P
Peter Mortensen

You can enable long path names using PowerShell:

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

Another version is to use a Group Policy in Computer Configuration/Administrative Templates/System/Filesystem:

https://i.stack.imgur.com/sifwu.png


Each application still has to declare that it's long-path aware. Microsoft has done a poor job communicating this by making it seem like the application manifest is just another way to enable this feature, rather than clearly explaining that it's a contract between the OS (system level policy) and application in which both have to agree.
Even Visual Studio 2019 Community doesn't support long paths, sadly
Even Windows Explorer doesn't support long path names either. It fakes it by using the short names when the path exceeds 260, but once you hit the 260 limit, you cannot see any folders or files below using the Windows Explorer app. You can access them from other apps written to support 32767 paths and also the command line, but not the UI of the Windows Explorer app. I am surprised in 2022 this is still an issue, but I heard Microsoft is working on pushing out a patch in Windows 10 and their new servers to support trying to fix it.
C
Conrad

As to why this still exists - MS doesn't consider it a priority, and values backwards compatibility over advancing their OS (at least in this instance).

A workaround I use is to use the "short names" for the directories in the path, instead of their standard, human-readable versions. So e.g. for C:\Program Files\ I would use C:\PROGRA~1\ You can find the short name equivalents using dir /x.


Short path names can be disabled in the registry (or was it the filesystem itself?), so this really isn't a dependable workaround.
@rubenvb I'm sure most if not all Windows features can be disabled in the registry so ¯\_(ツ)_/¯
Generating short names can be disabled for NTFS (and should be because it's inefficient in many cases), either for the whole system or per volume, so it is an unreliable approach even for paths on the system drive, which must be NTFS. It's possible to manually set short names on files and directories in NTFS, but this doesn't extend to newer filesystems that do not support short names at all, such as exFAT and ReFS. Short names should be considered a deprecated feature that's retained for compatibility in limited cases, like the old ANSI/OEM API using single- and double-byte codepages.
@eryksun Please see my previous comment about disabling short path names. :) Just because you think it should be considered deprecated, doesn't mean it actually is. MS has no plans to deprecate this feature. (Also, why are you installing Windows software on exFAT/ReFS partitions?)
I still say to just use non-normalized device paths (i.e. "\\?\" prefix), since they're always available and obvious. For example, translate PATH and pass it to SearchPathW. It's efficient, too, since the runtime library creates "\\?\" device paths for NT anyway. As to newer filesystems, we probably wouldn't see software installed on an exFAT volume, other than portable applications, since it has no security, but I wouldn't rule out ReFS. Users install programs in non-standard locations for reasons of convenience, space, or performance.
C
Community

As to how to cope with the path size limitation on Windows - using 7zip to pack (and unpack) your path-length sensitive files seems like a viable workaround. I've used it to transport several IDE installations (those Eclipse plugin paths, yikes!) and piles of autogenerated documentation and haven't had a single problem so far.

Not really sure how it evades the 260 char limit set by Windows (from a technical PoV), but hey, it works!

More details on their SourceForge page here:

"NTFS can actually support pathnames up to 32,000 characters in length." 7-zip also support such long names. But it's disabled in SFX code. Some users don't like long paths, since they don't understand how to work with them. That is why I have disabled it in SFX code.

and release notes:

9.32 alpha 2013-12-01 Improved support for file pathnames longer than 260 characters. 4.44 beta 2007-01-20 7-Zip now supports file pathnames longer than 260 characters.

IMPORTANT NOTE: For this to work properly, you'll need to specify the destination path in the 7zip "Extract" dialog directly, rather than dragging & dropping the files into the intended folder. Otherwise the "Temp" folder will be used as an interim cache and you'll bounce into the same 260 char limitation once Windows Explorer starts moving the files to their "final resting place". See the replies to this question for more information.


I was wrong, 7zip and WinRAR do extract all the folders and files. It's just that the property of a folder in Windows only reports the number of folder and files that don't violate the limitation. It's as if that Windows Explorer doesn't dig any deeper to discover folders when the max path is reached.
It is possible to delete a long path in 7-zip with shift-del.
Short answer - use 7zip to unzip a .zip file....worked for me on Windows 7
Beware of 7zip as the latest version in 2022 successfully zipped a WIM file, but failed to restore a WIM file properly. DISM restored the WIM file properly when created by 7zip. Something to be aware of. Use the \\?\ prefix in front of all drive letter paths to trigger 7zip to work with 32,767 length paths to ZIP or WIM up.
s
shA.t

It does, and it is a default for some reason, but you could easily override it with this registry key:

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem]
"LongPathsEnabled"=dword:00000001

See: https://blogs.msdn.microsoft.com/jeremykuhne/2016/07/30/net-4-6-2-and-long-paths-on-windows-10/


e
eliblanco87

Another way to cope with it is to use Cygwin, depending on what do you want to do with the files (i.e. if Cygwin commands suit your needs)

For example it allows to copy, move or rename files that even Windows Explorer can't. Or of course deal with the contents of them like md5sum, grep, gzip, etc.

Also for programs that you are coding, you could link them to the Cygwin DLL and it would enable them to use long paths (I haven't tested this though)


How does it avoid the limit? Isn't it dependent on the underlying file system (not a rhetorical question)? Did you test it? Do you have a reference you could add to your answer? (But without "Edit:", "Update:", or similar - the answer should appear as if it was written today.)
The Windows Command Line does support 32,767 path lengths. The issue is for legacy apps using the older WIN32 API which only supports a hard coded, compiled in limit of 260 characters. The Windows Explorer UI Application is the issue. It still uses the old WIN32 API and doesn't support overriding the PATH to use an UNC PATH. While the UI takes a UNC PATH, it will refactor it after you hit the enter key and change it back and then fail on long paths (even after refactoring to short names if enabled). I tried it.