Я несколько раз сталкивался с этой проблемой в неподходящие моменты:
Почему этот предел существует?
Почему он еще не удален?
Как вы справляетесь с лимитом пути?... и нет, переход на Linux или Mac OS X не является верным ответом на этот вопрос;)
Цитата этой статьи 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 достаточно ОЗУ.
Это не совсем верно, так как файловая система NTFS поддерживает пути до 32 тыс. символов. Вы можете использовать префикс win32 api и "\\?\
" для использования более 260 символов.
Подробное объяснение длинного пути от блога .Net BCL.
Небольшая выдержка подчеркивает проблему с длинными путями
Еще одна проблема заключается в непоследовательном поведении, которое может быть вызвано оказанием поддержки длинного пути. Длинные пути с префиксом
\\?\
могут использоваться в большинстве связанных с файлами API Windows, но не во всех API Windows. Например, LoadLibrary, которая отображает модуль в адрес вызывающего процесса, терпит неудачу, если имя файла больше MAX_PATH. Таким образом, это означает, что MoveFile позволит вам переместить DLL в такое местоположение, чтобы его путь был длиннее 260 символов, но при попытке загрузить DLL он потерпит неудачу. В Windows API есть аналогичные примеры; существуют некоторые обходные пути, но они основаны на каждом конкретном случае.
Вопрос , почему ограничение все еще существует. Конечно, современные Windows могут увеличить сторону MAX_PATH
, чтобы позволить более длинные пути. Почему ограничение не было удалено?
Через 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
. Вы также можете включить новое поведение длинного пути для каждого приложения через манифест:<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
Один из способов справиться с лимитом пути - сократить записи пути с символическими ссылками.
Например:
C:\p
, чтобы сохранить короткие ссылки на длинные пути.mklink /J C:\p\foo C:\Some\Crazy\Long\Path\foo
C:\p\foo
к вашему пути вместо длинного путиКак справиться с ограничением по размеру пути в 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 начнет перемещать файлы в их "конечное место отдыха". См. Ответы на этот вопрос для получения дополнительной информации.
Что до сих пор существует - MS не считает его приоритетом и сравнивает обратную совместимость перед продвижением своей ОС (по крайней мере, в этом случае).
Обходной путь, который я использую, заключается в использовании "коротких имен" для каталогов в пути, а не их стандартных, понятных для человека версий. Так, например, для C:\Program Files\
Я бы использовал C:\PROGRA~1\
. Вы можете найти короткие эквиваленты имен, используя dir /x
.
Вы можете включить длинные имена путей, используя PowerShell:
Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem' -Name LongPathsEnabled -Type DWord -Value 1
Другая версия - использовать групповую политику в Computer Configuration
/Administrative Templates
/System
/Filesystem
:
Это так, и по какой-то причине это значение по умолчанию, но вы можете легко переопределить его следующим ключом реестра:
[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/.
Еще один способ справиться с этим - использовать Cygwin, в зависимости от того, что вы хотите делать с файлами (т.е. если команды Cygwin соответствуют вашим потребностям)
Например, он позволяет копировать, перемещать или переименовывать файлы, которые даже Windows Explorer не может. Или, конечно, иметь дело с их содержимым, например md5sum, grep, gzip и т.д.
Также для программ, которые вы кодируете, вы можете связать их с DLL Cygwin, и это позволит им использовать длинные пути (я еще не тестировал это).
В то время как все кричат, что 260 символов ужасны в 2017 году, почему-то никто не кричит, что большинство gnu shitware ломается, если он сталкивается с пробелами в дорожках. Даже не unicode. И говоря о неотъемлемо сломанных функциях - подумайте о своем любимом strcpy
без n
. Даже malloc
разбивается на linux, потому что он полагается на ошибки страницы, чтобы фактически зарезервировать зарезервированное адресное пространство (которое медленное и подверженное ошибкам). Никто не совершенен, и невежество не является веской причиной для нытья.
Кроме того, комментаторы почему-то не говорят, что именно сломано.
Есть три вещи, которые сломаны:
определенные вызовы (я знаю только о Get/SetCurrentDirectoryW) ограничены одним потоком и 260 символами независимо от того, что. Таким образом, по существу относительные пути разбиваются на Windows, эмулируют их так же, как вы эмулируете fork
, если вы вынуждены.
программное обеспечение, перенесенное из не-окон, которое по своей сути полагается на концепции, отличные от окон (включая понятие текущих путей/относительных путей, см. выше)
программное обеспечение, написанное с нуля для Windows, но по-прежнему использует древний API (но см. выше), хотя есть API для общего доступа к файловой системе, нет API для текущего каталога в Windows, который работает после MAX_PATH)
Что касается того, почему он все еще сломался - по-моему, MS исправила все, что можно исправить. Я думаю, что это наследование текущего каталога дочерними процессами, который не позволяет фиксировать GetCurrentDirectoryW.