Почему ограничение длины пути 260 символов существует в Windows?

Я сталкивался с этой проблемой несколько раз в неподходящие моменты:

  • попытка работать над проектами Java с открытым исходным кодом с глубокими путями
  • хранение глубоких деревьев FitNesse wiki в системе управления версиями
  • ошибка при попытке использовать Bazaar для импорта дерева управления версиями

Почему существует этот предел?

Почему его еще не удалили?

Как вы справляетесь с ограничением пути? ... и нет, переход на linux или Mac OS X не является допустимым ответом на этот вопрос;)

12 ответов


цитируя эту статью http://msdn.microsoft.com/en-us/library/aa365247 (VS.85).aspx#maxpath

Ограничение Максимальной Длины Пути

в API Windows (за некоторыми исключениями, описанными в следующих параграфах) максимальная длина пути -в max_path, который определяется как 260 символов. Локальный путь структурирован в следующем порядке: буква диска, двоеточие, обратная косая черта, компоненты имен разделены обратную косую черту и символ null. Например, максимальный путь на диске D - " D:\некоторая 256-символьная строка пути " где " " представляет невидимый завершающий нулевой символ для текущей системной кодовой страницы. (Символы используются здесь для визуальной ясности и не могут быть частью допустимой строки пути.)

теперь мы видим, что это 1+2+256+1 или [drive] [:\] [path][null] = 260. Можно предположить, что 256-разумная фиксированная строка длина от дней DOS. И возвращаясь к API DOS, мы понимаем, что система отслеживала текущий путь на диск, и у нас есть 26 (32 с символами) максимальные диски (и текущие каталоги).

INT 0x21 AH=0x47 говорит: "эта функция возвращает описание пути без буквы диска и начальной обратной косой черты."Итак, мы видим, что система хранит CWD как пару (диск, путь) , и вы спрашиваете путь, указав диск (1=A, 2=B,...), если вы укажете a 0 затем он принимает путь для диска, возвращаемого INT 0x21 AH=0x15 AL=0x19. Итак, теперь мы знаем, почему это 260, а не 256, потому что эти 4 байта не хранятся в строке пути.

Почему строка пути 256 байтов, потому что 640K достаточно ОЗУ.


это не совсем верно, так как файловая система NTFS поддерживает пути до 32K символов. Вы можете использовать win32 api и"\?\" префикс пути для использования более 260 символов.

подробное объяснение длинного пути из .Net блог команды BCL.
Небольшой отрывок подчеркивает проблему с длинными путями

другая проблема-непоследовательное поведение, которое приведет к предоставлению поддержки длинного пути. Длинные пути с \?\ префикс может использоваться в большинстве связанных с файлами API Windows, но не во всех API Windows. Например, LoadLibrary, который сопоставляет модуль с адресом вызывающего процесса, завершается ошибкой, если имя файла длиннее MAX_PATH. Таким образом, это означает, что MoveFile позволит вам переместить DLL в такое место, чтобы его путь был длиннее 260 символов, но при попытке загрузить DLL он потерпит неудачу. Во всех API-интерфейсах Windows есть аналогичные примеры; некоторые обходные пути существуют, но они в каждом конкретном случае основа.


вопрос почему ограничение все еще существует. Конечно, современные окна могут увеличить сторону MAX_PATH разрешить более длинные пути. Почему это ограничение не снято?

  • причина, по которой его нельзя удалить, заключается в том, что Windows обещала, что он никогда не изменится.

через контракт API Windows гарантировала всем приложениям, что стандартные файловые API никогда не вернут путь длиннее 260 письмена.

рассмотрим следующее правильно код:

WIN32_FIND_DATA findData;

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

окна гарантированный моя программа, что она будет заполнять мой WIN32_FIND_DATA структура:

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

мое приложение не объявило значение константы MAX_PATH, API Windows сделал. Мое приложение использовало это определенное значение.

моя структура правильно определена и выделяет только 592 байт. Это означает, что я могу только получите имя файла, которое меньше 260 символы. Окна обещал мне, что если я правильно написал мое заявление, мое приложение будет продолжать работать в будущем.

если бы Windows разрешала имена файлов длиннее 260 символы, то мое существующее приложение (которое использовало правильный API правильно) потерпит неудачу.

для тех, кто призывает Microsoft изменить MAX_PATH константа, им сперва нужно обеспечить что никакое существующее применение неудачи. Например, я все еще владею и использую приложение Windows, которое было написано для запуска в Windows 3.11. Он по-прежнему работает на 64-разрядной Windows 10. Вот что дает обратная совместимость.

Microsoft сделал создайте способ использовать полные 32 768 имен путей; но для этого им пришлось создать новый контракт API. Во-первых, вы должны использовать Shell API для перечисления файлов (так как не все файлы находятся на жестком диске или сетевом ресурсе).

но они также не должны нарушать существующие пользовательские приложения. Подавляющее большинство приложений не используйте api оболочки для работы с файлами. Все просто звонят FindFirstFile/FindNextFile и все.


Из Windows 10. ты можешь!--5-->снять ограничение путем изменения ключей реестра.

Совет начиная с 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. Вы также можете включить новый long поведение пути для приложения через манифест:

<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:\path\to\long\folder вы можете отобразить его на букву диска X: использование:

subst x: \path\to\long\folder

один из способов справиться с ограничением пути-сократить записи пути с символическими ссылками.

например:

  1. создать C:\p каталог, чтобы сохранить короткие ссылки на длинные пути
  2. mklink /J C:\p\foo C:\Some\Crazy\Long\Path\foo
  3. добавить C:\p\foo к вашему пути вместо длинного пути

как Почему это все еще существует-MS не считает это приоритетом и оценивает обратную совместимость по сравнению с продвижением своей ОС (по крайней мере, в этом случае).

обходной путь, который я использую, заключается в использовании "коротких имен" для каталогов в пути вместо их стандартных, удобочитаемых версий. Так что например на C:\Program Files\ Я хотел бы использовать C:\PROGRA~1\ вы можете найти эквиваленты коротких имен, используя dir /x.


Как справиться с ограничением размера пути в Windows-с помощью в 7-Zip упаковать (и распаковать) ваши конфиденциальные файлы длины пути кажется жизнеспособным обходным путем. Я использовал его для транспортировки нескольких установок IDE (эти пути плагинов Eclipse, yikes!) и кучи автогенерируемые документации и не было ни одной проблемы до сих пор.

не совсем уверен, как он уклоняется от ограничения 260 char, установленного Windows (из технического PoV), но эй, это работает!

подробнее на их странице SourceForge здесь:

"NTFS может фактически поддерживать пути до 32 000 символов в длина."

7-Zip также поддерживает такие длинные имена.

но он отключен в коде SFX. Некоторые пользователи не любят длинные пути, так как они не понимают, как с ними работать. Вот почему я отключил его в коде SFX.

и релиз Примечания:

9.32 Альфа 2013-12-01

  • улучшена поддержка имен файлов длиной более 260 символов.

4.44 beta 2007-01-20

  • 7-Zip теперь поддерживает пути к файлам длиной более 260 символов.

ВАЖНОЕ ПРИМЕЧАНИЕ: чтобы это работало правильно, вам нужно указать путь назначения в в 7-Zip Диалог" извлечение " напрямую, а не перетаскивание файлов в нужную папку. В противном случае папка" Temp "будет использоваться в качестве временного кэша, и вы будете отскакивать в то же ограничение 260 символов, как только Проводник Windows начнет перемещать файлы в их"окончательное место отдыха". См. ответы на этот вопрос для получения дополнительной информации.


еще один способ справиться с этим-использовать Cygwin, в зависимости от того, что вы хотите сделать с файлами (т. е. если команды в Cygwin под свои нужды)

например, он позволяет копировать, перемещать или переименовывать файлы, которые даже проводник Windows не может. Или, конечно, иметь дело с их содержимым, таким как md5sum, grep, gzip и т. д.

также для программ, которые вы кодируете, вы можете связать их с DLL Cygwin, и это позволит им использовать длинные пути (я не тестировал это хотя)


это так, и по какой-то причине это значение по умолчанию, но вы можете легко переопределить его с помощью этого раздела реестра:

[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 

другая версия - использовать групповую политику в Computer Configuration/Administrative Templates/System/Filesystem:

Group Policy Editor


в то время как все плачут, что 260 символов ужасны в 2017 году, почему-то никто не плачет, что большинство GNU shitware ломается, если он сталкивается с пространствами в путях. Даже Юникод. И говоря о изначально сломанных функциях-подумайте о своем любимом strcpy без n. Даже malloc сломан в linux, потому что он полагается на ошибки страницы, чтобы фактически зафиксировать зарезервированное адресное пространство (которое медленно и подвержено ошибкам). Никто не совершенен, и невежество не является веской причиной, чтобы ныть.

кроме того, комментаторы как-то не говорят, что именно сломано.

есть 3 вещи, которые разбиты:

  • некоторые вызовы (я знаю только Get/SetCurrentDirectoryW) ограничены одним потоком и 260 символами независимо от того, что. Таким образом, по существу относительные пути разбиты на окна, эмулировать их так же, как вы эмулировать fork Если вы вынуждены.

  • программное обеспечение, портированное из не-windows, которое по своей сути полагается на концепции, отличные от windows (включая концепцию текущих dir/относительных путей, см. выше)

  • программное обеспечение, которое написано с нуля для Windows, но по - прежнему использует древний API (но см. выше-хотя есть API для общего доступа к файловой системе, нет API для текущего каталога в Windows, который работает мимо MAX_PATH)

что касается того, почему он все еще сломан - на мой взгляд, MS исправила все, что можно исправить. Я думаю это наследование текущего каталога дочерними процессами, которое не позволяет исправлять GetCurrentDirectoryW.