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


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

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

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

Почему он еще не был удален?

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

12 330

12 ответов:

цитировании этой статьи http://msdn.microsoft.com/en-us/library/aa365247(против.85).аспн#maxpath

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

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

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

INT 0x21 AH=0x47 говорит: "эта функция возвращает описание пути без буквы диска и начальной обратной косой черты."Таким образом, мы видим, что система хранит CWD как пару (диск, путь), и вы просите путь, указав диск (1=A, 2=B,...), если вы укажете a 0, то предполагается, что путь на диск, возвращаемый тип int 0x21 ах=0x15 АЛ=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);

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, которое было написано для запуска в Windows 3.11. Он по-прежнему работает на 64-разрядной Windows 10. Вот что дает вам обратная совместимость.

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

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

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

Совет начиная с 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 - using в 7-Zip чтобы упаковать (и распаковать) ваши файлы, чувствительные к длине пути, кажется жизнеспособным обходным путем. Я использовал его для транспортировки нескольких установок IDE (эти пути плагина Eclipse, yikes!) и кучи автогенерируемые документации и не было ни одной проблемы до сих пор.

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

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

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

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

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

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

9.32 Альфа 2013-12-01

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

бета 4.44 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.