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

341

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

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

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

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

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

  • 7
    @Artelius: На самом деле Windows (по крайней мере, начиная с Win2K) поддерживает точки соединения ( en.wikipedia.org/wiki/NTFS_junction_point ), а Vista и далее поддерживают символические ссылки NT ( en.wikipedia.org/wiki/NTFS_symbolic_link ). В любом случае, хотя символические ссылки могут помочь сделать более длинные / вложенные пути более удобными, я не могу себе представить, как эти ссылки помогут, если вы достигнете ограничений длины пути.
  • 8
    Плохая новость: это никогда не будет исправлено. visualstudio.uservoice.com/forums/121579-visual-studio/...
Показать ещё 9 комментариев
Теги:
path
limit

12 ответов

206
Лучший ответ

Цитата этой статьи http://msdn.microsoft.com/en-us/library/aa365247(VS.85).aspx#maxpath

Максимальное ограничение длины пути

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

Теперь мы видим, что это 1 + 2 + 256 + 1 или [диск] [: \] [путь] [null] = 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 байт, потому что 640K достаточно ОЗУ.

  • 18
    Windows API ограничивает длину даже в самой последней ОС. Microsoft боится нарушить работу сотен миллионов операционных систем сегодня, если это изменится, потому что у них больше не работают гении, которые понимают API внутри и снаружи, как они это делали в 1980-х и 1990-х годах. Риск не стоит его менять. serverfault.com/questions/163419/...
  • 2
    ... по той же причине они хранят 64-битные драйверы в папке system32 и 32-битные драйверы в папке SysWOW64. Риск торможения оригинального Windows API может привести к банкротству, потому что их разработчики недостаточно хорошо это понимают.
Показать ещё 21 комментарий
128

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

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

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

  • 4
    Справедливо, но это означает, что вы должны использовать P / Invoke во многих местах, и это, на мой взгляд, снижает переносимость вашего .Net кода. Что если я хочу сохранить моно-совместимость?
  • 1
    Я хотел сказать, что вы можете использовать длинный путь, если вы действительно этого хотите. Но я согласен, что это боль, и лично я бы этого также избежал.
Показать ещё 3 комментария
90

Вопрос , почему ограничение все еще существует. Конечно, современные 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 и называет это днем.

  • 0
    Разве Windows не может прозрачно переводить длинные пути в более короткие в качестве прокладки с обратной совместимостью? Я считаю, что Windows 9x сделала что-то подобное для совместимости с DOS.
  • 3
    @JosiahKeller В противном случае он нарушит контракт, изначально определенный для этого метода, и это может перезаписать непреднамеренную память и, по сути, открыть дыру в безопасности. Единственный способ исправить это - предложить новый улучшенный API (например, варианты с поддержкой Unicode) и надеяться, что все перекомпилируют / повторно выпускают все свои приложения, используя более новый API.
Показать ещё 19 комментариев
38

В 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>
  • 9
    К сожалению, даже в последней версии Win10, сам File Explorer все еще имеет проблемы с длинным путем. Даже «Копировать как путь» в контекстном меню не работает должным образом; это только скопировать первые 260 символов. Вы не можете создать папку, скопировать / переместить / открыть файл ... Заставьте меня задуматься, в чем смысл этого изменения.
  • 0
    @ raymai97 Еще через 20 лет .. :)
28

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

subst x: \path\to\long\folder
  • 0
    я получаю "Неверный параметр J:" при попытке этой команды
  • 0
    Это должно быть запущено из командной строки администратора (с повышенными правами).
Показать ещё 4 комментария
13

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

Например:

  • создайте каталог C:\p, чтобы сохранить короткие ссылки на длинные пути.
  • mklink /J C:\p\foo C:\Some\Crazy\Long\Path\foo
  • добавить C:\p\foo к вашему пути вместо длинного пути
  • 3
    Не нужно было сначала создавать каталог, поэтому шаг 1 не требуется.
  • 0
    Отлично работает на Ant / Java, спасибо!
Показать ещё 1 комментарий
6

Как справиться с ограничением по размеру пути в 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 начнет перемещать файлы в их "конечное место отдыха". См. Ответы на этот вопрос для получения дополнительной информации.

  • 3
    Я был неправ, 7zip и WinRAR действительно распаковывают все папки и файлы. Просто свойство папки в Windows сообщает только количество папок и файлов, которые не нарушают ограничение. Как будто Windows Explorer не копает глубже, чтобы обнаружить папки, когда достигнут максимальный путь.
  • 0
    Можно удалить длинный путь в 7-zip с помощью shift-del.
Показать ещё 1 комментарий
6

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

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

  • 1
    Короткие пути могут быть отключены в реестре (или это была сама файловая система?), Так что это действительно не надежный обходной путь.
  • 1
    @rubenvb Я уверен, что большинство, если не все функции Windows могут быть отключены в реестре, так что ¯ \ _ (ツ) _ / ¯
1

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

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

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

Изображение 7242

1

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

[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/.

1

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

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

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

-2

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

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

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

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

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

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

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

  • 0
    Проблема в том, что создание пути длиннее 260 символов тривиально для любого программного обеспечения. Работа с ним позже становится проблемой - все программное обеспечение внезапно не может открыть его, включая все программное обеспечение, написанное Microsoft, как весь набор инструментов VC.
  • 0
    Как я уже говорил выше, только программное обеспечение, которое использует вызовы CurrentDirectory, по сути неисправно и не подлежит восстановлению. Например, в Word нет никаких причин полагаться на текущий каталог, поэтому он должен работать. С набором инструментов это сложно. Мы можем провести повторное тестирование, чтобы увидеть, может ли, например, cl.exe создавать файлы при наличии длинного пути. Если это возможно, то это «только» MSBuild / VS, которые сломаны :) Я думаю, вы видите мои рассуждения: ясно, что инструменты командной строки, как правило, полагаются на текущий каталог. Я не думаю, что идея Microsoft о том, что текущий каталог бесполезен в многопоточной разработке, по своей сути нарушена.
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню