0

On Windows 10 Home and Python 3.6.6, I have enabled long paths by setting it in the registry and by prefixing \\?\. I have also followed this answer and ensured that the path uses \\ instead of /, is in unicode u' and is an absolute path. There are no illegal characters in my file name. My file path is also way smaller than the maximum total path length of 32,767 characters.

Despite doing all of the above, I still get OSError: [Errno 22] Invalid argument when I try to create a long file name. I have tried 3 different ways of creating the filepath as output_filepath below but all do not work:

# Long filename - Does not work
import os, pathlib
output_filepath = u'\\\\?\\' + os.path.join(os.path.dirname(os.path.realpath(__file__)), u"somereallylongname" * 30 + u".result")
# output_filepath = u'\\\\?\\C:\\Users\\Jarrett\\Downloads\\somereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongname\\x.x'
# output_filepath = r'\\?\C:\Users\Jarrett\Downloads\somereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongname\x.x'
print("filepath length = %s" % len(output_filepath))
print("filename length = %s" % len(os.path.basename(output_filepath)))
if not os.path.exists(os.path.dirname(output_filepath)): os.makedirs(os.path.dirname(output_filepath))
pathlib.Path(output_filepath).touch() # or open(output_filepath, 'a').close()
print("Wrote to " + output_filepath)
user5305519
  • 3,008
  • 4
  • 26
  • 44
  • Strings in Python 3 are unicode; there's no need to use the `u` prefix from Python 2. Also, if you're using Python 3.6+ and Windows 10, and you've enabled long paths in the registry, then you do not need to use an extended path (i.e. non-normalized device path) in the "\\?\" device root path. You can use regular DOS paths. The problem, as discussed below by Drake, is that the filesystem's maximum component length is fixed per its internal data structures, and absolutely nothing can change that. – Eryk Sun May 06 '20 at 09:35
  • 1
    The Windows API itself has a similar component length limit baked into the result of a directory listing from `FindFirstFileW` / `FindNextFileW`, as called internally by Python's `os.listdir` and `os.scandir`. The API limits names in a directory listing to `MAX_PATH` (260) characters. Note that in this case they've reused the `MAX_PATH` constant, though the names in a directory listing are not paths. – Eryk Sun May 06 '20 at 09:40

1 Answers1

0

The file name component (the part between the backslashes in the file name) is too long, the Max number of Component Length depends on the value returned in the lpMaximumComponentLength parameter of the GetVolumeInformation function.

For example, for a FAT file system that supports long names, the function stores the value 255.

Try to shorten the length of the file name component, like:

import os, pathlib
output_filepath = u'\\\\?\\' + os.path.join(os.path.dirname(os.path.realpath(__file__)), u"somereallylongname" * 14 + u'\\' + u"somereallylongname" * 14 + u'\\' + u"somereallylongname" * 2 + u".result")
# output_filepath = u'\\\\?\\C:\\Users\\Jarrett\\Downloads\\somereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongname\\x.x'
# output_filepath = r'\\?\C:\Users\Jarrett\Downloads\somereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongnamesomereallylongname\x.x'
print(output_filepath)
print("filepath length = %s" % len(output_filepath))
print("filename length = %s" % len(os.path.basename(output_filepath)))
if not os.path.exists(os.path.dirname(output_filepath)): os.makedirs(os.path.dirname(output_filepath))
pathlib.Path(output_filepath).touch() # or open(output_filepath, 'a').close()
print("Wrote to " + output_filepath)
Drake Wu
  • 6,927
  • 1
  • 7
  • 30
  • Thanks for the reply. In other words what you are saying is that filepath can be >255 but filename cannot, thus the error? – user5305519 May 06 '20 at 07:09
  • Yes, according to the last document you linked, "*...permit an extended-length path for a maximum total path length of 32,767 characters. This type of path is composed of components separated by backslashes, each up to the value returned in the `lpMaximumComponentLength` parameter of the [`GetVolumeInformation`](https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getvolumeinformationa) function (this value is commonly 255 characters). ...*" – Drake Wu May 06 '20 at 07:22
  • "*but filename cannot*", and the directory name between backslashes. – Drake Wu May 06 '20 at 07:45
  • Hi, @jarrettyeo does this answer your question? – Drake Wu May 06 '20 at 10:12