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

390

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

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

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

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

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

Джеффри Кэмерон
источник
8
@Artelius: На самом деле, Windows (по крайней мере, начиная с Win2K) поддерживает точки соединения ( en.wikipedia.org/wiki/NTFS_junction_point ), а Vista и далее поддерживают символические ссылки NT ( en.wikipedia.org/wiki/NTFS_symbolic_link ). В любом случае, хотя символические ссылки могут помочь сделать более длинные / вложенные пути более удобными, я не могу себе представить, как эти ссылки помогут, если вы достигнете ограничений длины пути.
Ашутош Мехра
8
Даже если этот предел не существует, всегда есть много других ограничений, и каждый из них может быть раздражающим в какой-то момент. Дело в том, почему этот предел так низок? После эпохи 8.3 и с аппаратными средствами мегабайта, путь должен теперь быть динамически распределенной строкой с практически неограниченным размером.
Роланд
12
Microsoft наконец-то решает эту проблему в Windows 10 Build 14352.
Уоррен П
3
Да, и похоже, что вам нужно изменить манифест приложения, чтобы он был в курсе.
Уоррен П
3
@PatrickSzalapski, к сожалению, это было исправлено visualstudio.uservoice.com/forums/121579-visual-studio/…
phuclv

Ответы:

231

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

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

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

Теперь мы видим, что это 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 КБ достаточно ОЗУ.

Valli
источник
21
Windows API ограничивает длину даже в самой последней ОС. Microsoft боится нарушить работу сотен миллионов операционных систем сегодня, если это изменится, потому что у них больше не работают гении, которые понимают API внутри и снаружи, как они это делали в 1980-х и 1990-х годах. Риск не стоит его менять. serverfault.com/questions/163419/…
MacGyver
77
@MacGyver Извините, но это полная чушь. Microsoft не хочет ломать миллионы плохо написанных приложений, которые предполагают вещи, которые никогда не были гарантированы. К сожалению, так долго все было так, что разработчики стали полагаться на них, поэтому изменение его сейчас может привести к поломке сторонних приложений, и виноват MS.
Основное
25
Между прочим, нет никаких доказательств того, что Гейтс когда-либо говорил, что «640 КБ достаточно для всех» computerworld.com/article/2534312
Патрик Фавр
11
@Basic Ограничение в 260 символов было гарантировано Windows. Константа была объявлена ​​как константа , в заголовочных файлах Windows была объявлена ​​структура, в которой есть место только для 260 символов. Нет способа изменить это.
Ян Бойд
35
@Basic Константа не меняется, как только она скомпилирована в мое приложение. Я запускаю приложение, которое было построено в 1994 году и до сих пор работает в Windows 10. Microsoft пообещала определенный размер двоичного блока памяти, и программист следовал этому правилу. Если бы Microsoft сменила константу, то каждое существующее приложение, правильно следовавшее API программирования, было бы повреждено . Вы не можете нарушить бинарную совместимость.
Ян Бойд
150

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

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

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

softveda
источник
4
Справедливо, но это означает, что вы должны использовать P / Invoke во многих местах, и это, на мой взгляд, уменьшает переносимость вашего .Net кода. Что если я хочу сохранить моно-совместимость?
Джеффри Кэмерон
1
Я хотел сказать, что вы можете использовать длинный путь, если вы действительно этого хотите. Но я согласен, что это боль, и лично я бы этого также избежал.
софтведа
5
Это должен быть выбранный ответ. Фактически отвечает на вопрос, заданный пользователем, ПОЧЕМУ этот предел существует И предоставляет обходной путь. Upvote для видимости
KyleMit
2
Мне кажется, что Microsoft нужно исправить их API, и я думаю, что это не является приоритетом. Я был удивлен, что этот предел все еще существует в Windows 8.
Mas
3
@Mas «Исправление», которое вы хотите, было сделано все назад к Windows XP. Вызов Unicode-версии их API позволит вам получить доступ к «расширенному пути». Я считаю, что проводник автоматически справляется с этим. Вот одна такая функция, которая поддерживает это - msdn.microsoft.com/en-us/library/windows/desktop/… .
Натали Адамс
108

Вопрос в том, почему ограничение все еще существует. Конечно, современные 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 сделал создать способ использовать полные имена путей 32768; но они должны были создать новый контракт API для этого. Во-первых, вы должны использовать Shell API для перечисления файлов (поскольку не все файлы существуют на жестком диске или в сетевой папке).

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

Ян Бойд
источник
4
@JosiahKeller В противном случае он нарушит контракт, изначально определенный для этого метода, и это может перезаписать непреднамеренную память и, по сути, открыть дыру в безопасности. Единственный способ исправить это - предложить новый улучшенный API (например, варианты с поддержкой Unicode) и надеяться, что все перекомпилируют / повторно выпускают все свои приложения, используя более новый API.
Роуланд Шоу
2
@Ryios Я не думаю, что мои существующие приложения Windows будут работать в Linux.
Ян Бойд
9
Обратная совместимость это хорошо. Но я думаю, что избегать таких (часто очень неприятных) проблем сегодня важнее, чем поддержка приложений Windows 3.1. Сколько людей сталкиваются с проблемами на длинных путях? И сколько людей все еще используют приложения Windows 3.1? Они даже отменили поддержку Windows XP. Так почему бы им просто не сделать объявление о том, что из Windows [x] и более поздних приложений, которые предполагают, что путь не будет длиннее 260 символов, не будет работать должным образом, когда они находят путь, который является длинным? Наши ограничения скорости также не касаются вагонов.
JuSchu
2
@JuSchu Это не просто приложения для Windows 3.1. Приложения, написанные сегодня с использованием правильного API, не будут работать.
Ян Бойд
62

В 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>
Корневая петля
источник
15
К сожалению, даже в последней версии Win10, сам File Explorer все еще имеет проблемы с длинным путем. Даже «Копировать как путь» в контекстном меню не работает должным образом; это только скопировать первые 260 символов. Вы не можете создать папку, скопировать / переместить / открыть файл ... Заставьте меня задуматься, в чем смысл этого изменения.
raymai97
Обратите внимание, что утверждение о том, что настройки системы не зависят от настроек манифеста, неверно. Оба требуются. Политика должна быть включена на системном уровне, а манифест должен объявить, что приложение поддерживает длинные пути.
Eryk Sun
Я прочитал, что внесение этого изменения может вызвать проблемы совместимости со старыми 32-разрядными приложениями, но является ли этот тип проблемы совместимостью распространенной? Я хотел бы внести изменения сам. lifehacker.com/…
ДПК
32

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

subst x: \path\to\long\folder
jonchang
источник
я
получаю
Это должно быть запущено из командной строки администратора (с повышенными правами).
Mrchief
Это не удастся с косыми чертами, необходимо иметь обратную косую черту.
cchamberlain
1
Я не уверен, относится ли это только к Windows 10, однако я только что обнаружил, что при попытке запустить эту команду, если я запускаюсь от имени администратора, как указано выше, диск оказывается недоступным. Это связано с тем, что поведение похоже на сопоставление сетевого диска и зависит от конкретного сеанса и т. Д., Поэтому, когда я запускался от имени администратора и использовал эту команду, этот сеанс мог использовать x: TL; DR. Если вы не видите, что диск пытается Запустите команду, не находясь в режиме администратора.
Джедди
substэто local-session / account - см. superuser.com/questions/29072/… чтобы узнать, как сделать его «общесистемным»
user2864740
18

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

Например:

  1. создать C:\pкаталог для хранения коротких ссылок на длинные пути
  2. mklink /J C:\p\foo C:\Some\Crazy\Long\Path\foo
  3. добавить C:\p\fooк вашему пути вместо длинного пути
JDiMatteo
источник
3
Не нужно было сначала создавать каталог, поэтому шаг 1 не требуется.
ohaal
2
Этот прием не всегда работает, так как многие приложения пытаются разрешить ссылки
nponeccop
/jОпция создает спая для монтирования локального устройства тома или путь на локальном томе (как Unix BIND монтирования). Это не создает символическую ссылку. Это важное различие, так как точки монтирования соединения всегда оцениваются на сервере и должны предназначаться для локальных устройств, тогда как символические ссылки оцениваются на клиенте и могут предназначаться для удаленных путей (если это разрешено политикой). Как и у диска subst.exe (т. Е. DefineDosDeviceW), Длина точки соединения обычно не превышает 4 КБ. На самом деле это 8K символов, равномерно распределенных между замещающим путем и путем отображения.
Eryk Sun
12

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

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

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

Редактор групповой политики

MovGP0
источник
2
Каждое приложение все еще должно объявить, что оно осведомлено о длинном пути. Microsoft проделала плохую работу, сообщив об этом, создавая впечатление, что манифест приложения - это просто еще один способ включить эту функцию, вместо того, чтобы четко объяснять, что это контракт между ОС (политикой системного уровня) и приложением, с которым оба должны согласиться.
Eryk Sun
8

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

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

Conrad
источник
1
Короткие пути могут быть отключены в реестре (или это была сама файловая система?), Так что это действительно не надежный обходной путь.
rubenvb
3
@rubenvb Я уверен, что большинство, если не все функции Windows могут быть отключены в реестре, так что ¯ \ _ (ツ) _ / ¯
Конрад
Генерацию коротких имен можно отключить для NTFS (и это должно быть потому, что во многих случаях это неэффективно), либо для всей системы, либо для каждого тома, поэтому это ненадежный подход даже для путей на системном диске, который должен быть NTFS. Можно вручную задать короткие имена для файлов и каталогов в NTFS, но это не распространяется на более новые файловые системы, которые вообще не поддерживают короткие имена, такие как exFAT и ReFS. Короткие имена следует рассматривать как устаревшую функцию, которая сохраняется для совместимости в ограниченных случаях, таких как старый API ANSI / OEM, использующий одно- и двухбайтовые кодовые страницы.
Eryk Sun
@eryksun Пожалуйста, смотрите мой предыдущий комментарий об отключении коротких путей. :) Если вы считаете, что это следует считать устаревшим, это еще не значит, что так оно и есть. MS не планирует отказываться от этой функции. (Кроме того, почему вы устанавливаете программное обеспечение Windows на разделы exFAT / ReFS?)
Конрад
Я по-прежнему говорю просто использовать ненормализованные пути устройств (то есть префикс «\\? \»), Поскольку они всегда доступны и очевидны. Например, перевести PATHи передать его SearchPathW. Это также эффективно, поскольку библиотека времени выполнения в любом случае создает "\\? \" Пути к устройствам для NT. Что касается более новых файловых систем, мы, вероятно, не увидим программное обеспечение, установленное на томе exFAT, кроме переносимых приложений, поскольку оно не имеет защиты, но я бы не стал исключать ReFS. Пользователи устанавливают программы в нестандартных местах по соображениям удобства, места или производительности.
Eryk Sun
7

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

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

Более подробная информация на их странице SourceForge здесь :

«NTFS может поддерживать имена путей длиной до 32 000 символов».

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

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

и примечания к выпуску :

9.32 альфа 2013-12-01

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

4.44 бета 2007-01-20

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

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

Прииду Нимре
источник
3
Я был неправ, 7zip и WinRAR действительно распаковывают все папки и файлы. Просто свойство папки в Windows сообщает только количество папок и файлов, которые не нарушают ограничение. Как будто Windows Explorer не копает глубже, чтобы обнаружить папки, когда достигнут максимальный путь.
Витой Шепот
Можно удалить длинный путь в 7-zip с помощью shift-del.
Лори Стерн
Краткий ответ - используйте 7zip для распаковки .zip файла .... у меня работало на Windows 7
andrewcockerham
2

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

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

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

eliblanco87
источник