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

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

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

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

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

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

Ответы

Ответ 1

Цитирую эту статью https://docs.microsoft.com/en-us/windows/desktop/FileIO/naming-a-file#maximum-path-length-limitation

Maximum Path Length Limitation

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

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

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

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

Ответ 2

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

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

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

Ответ 3

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

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

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

Ответ 4

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

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

Ответ 5

Вы можете установить папку в качестве диска. Из командной строки, если у вас есть путь C:\path\to\long\folder, вы можете сопоставить его с буквой диска X:, используя:

subst x: \path\to\long\folder

Ответ 6

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

Например:

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

Ответ 7

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

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

Ответ 8

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

Не уверен, как он уклоняется от предела 260 char, установленного 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 "Извлечь", а не перетаскивать файлы в нужную папку. В противном случае папка "Temp" будет использоваться в качестве промежуточного кеша, и вы будете отскакивать от того же 260 char, как только проводник Windows начнет перемещать файлы в их "конечное место отдыха". См. Ответы на этот вопрос для получения дополнительной информации.

Ответ 9

Вы можете включить длинные имена путей, используя PowerShell:

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

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

Group Policy Editor

Ответ 11

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

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

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

Ответ 12

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

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

Есть три вещи, которые сломаны:

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

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

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

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