Чому обмеження довжини шляху 260 символів існує в Windows?


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 та обладнання з розміром мега / гіга тепер шлях повинен бути динамічно виділеною рядком практично необмеженого розміру.
Roland

12
Microsoft нарешті вирішує цю проблему в Windows 10 Build 14352.
Warren P

3
Так, і схоже, що вам доведеться змінити маніфест програми, щоб зрозуміти довгий шлях.
Warren P

3
@PatrickSzalapski, на жаль, було виправлено visualstudio.uservoice.com/forums/121579-visual-studio/…
phuclv

Відповіді:


230

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

Максимальне обмеження довжини шляху

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

Тепер ми бачимо, що це 1 + 2 + 256 + 1 або [drive] [: \] [path] [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 достатньо оперативної пам'яті.


21
API Windows обмежує довжину навіть в останніх ОС. Microsoft боїться зламати сотні мільйонів операційних систем, які використовуються сьогодні, якби це змінилося, оскільки для них вже не працюють генії, які розуміють API всередині та зовні, як це було у 1980-х та 1990-х роках. Ризик змінювати його не варто. serverfault.com/questions/163419/…
MacGyver

77
@MacGyver Вибачте, але це суцільна нісенітниця. Microsoft не хоче ламати мільйони погано написаних програм, які передбачають, що в системі не було гарантовано. На жаль, так довго йшов той самий шлях, що розробники почали покладатися на них, тож змінивши його зараз, це порушить додатки сторонніх виробників, і MS візьме на себе вину.
Основні

25
btw немає жодних доказів того, що Гейтс коли-небудь говорив, що "640 КР вистачає на всіх" computerworld.com/article/2534312
Патрік Фавр

11
@Basic Межа 260 символів гарантувала Windows. Константа була оголошена константою , структура була оголошена у файлах заголовків Windows, у яких розміщено лише 260 символів. Неможливо змінити це.
Ян Бойд

35
@Basic Константа не змінюється після її складання в мою програму. Я запускаю додаток, який востаннє був побудований у 1994 році і досі працює у Windows 10. Microsoft пообіцяла певний бінарний розмір блоку пам'яті, і програміст дотримувався цього правила. Якби Microsoft змінила константу, то кожна існуюча програма, яка правильно дотримувалася API програмування, була б порушена . Ви не можете порушити бінарну сумісність.
Ян Бойд

150

Це не зовсім вірно, оскільки файлова система NTFS підтримує шляхи до 32 к символів. Ви можете використовувати ap32 win32 та \\?\префікс шляху, щоб використовувати більше 260 символів.

Детальне пояснення довгого шляху з блогу команди .Net BCL .
Невеликий уривок висвітлює проблему довгими шляхами

Інше занепокоєння викликає непослідовність поведінки, яка виникла б під впливом довгої підтримки. Довгі шляхи з \\?\префіксом можна використовувати в більшості файлів, пов'язаних з файлами API, але не у всіх API API. Наприклад, LoadLibrary, який відображає модуль на адресу процесу виклику, виходить з ладу, якщо ім'я файлу довше MAX_PATH. Таким чином, це означає, що MoveFile дозволить вам перемістити DLL в таке місце, щоб шлях не перевищував 260 символів, але якщо ви спробуєте завантажити DLL, це не вдасться. Подібні приклади є у всіх API API; деякі обхідні шляхи існують, але вони є для кожного конкретного випадку.


4
Досить справедливо, але це означає, що вам доведеться використовувати P / Invoke у багатьох місцях, і це, на мій погляд, знижує портативність вашого коду .Net. Що робити, якщо я хотів би зберегти Mono-сумісність?
Джефрі Кемерон

1
Моя думка полягала в тому, що ви можете використовувати довгий шлях, якщо цього дуже хотіли. Але я погоджуюсь, що це біль і особисто я б цього також уникав.
софтведа

5
Це має бути обрана відповідь. Насправді відповідає на питання, поставлене користувачем ЧОМУ існує цей ліміт І забезпечує обхід. Оновлення на видимість
KyleMit

2
Мені здається, що Microsoft має виправити свої API, і я думаю, це не є пріоритетним. Мене здивувало, що цей ліміт все ще існує у Windows 8.
Мас

3
@Mas "Виправлення", яке ви хочете, було зроблено назад у Windows XP. Виклик версії 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, це зробив API Windows. Моя програма використовувала це визначене значення.

Моя структура правильно визначена і виділяє лише 592байти. Це означає, що я можу отримувати лише ім’я файлу, менший за кількість 260символів. Windows пообіцяла мені, що якщо я правильно напишу заявку, моя програма продовжуватиме працювати в майбутньому.

Якби Windows мала дозволити назви файлів довше, ніж 260символи, тоді мій існуючий додаток (який правильно використовував правильний API) не зможе.

Для всіх, хто закликає Microsoft змінити MAX_PATHконстанту, вони спочатку повинні переконатися, що жодна існуюча програма не працює. Наприклад, я все ще є власником і використовую додаток Windows, яке було написано для роботи в Windows 3.11. Він все ще працює у 64-розрядної Windows 10. Саме тому ви отримуєте зворотну сумісність.

Microsoft зробив створити спосіб використовувати повні імена шляхів 32768; але їм довелося створити новий контракт API, щоб це зробити. Для одного, ви повинні використовувати API Shell для перерахування файлів (оскільки не всі файли існують на жорсткому диску або спільній мережі).

Але вони також повинні не порушувати існуючі користувацькі програми. Переважна більшість додатків не використовують оболонки 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, сам Провідник файлів все ще має проблеми з назвою довгого шляху. Навіть "Копіювати як шлях" у контекстному меню працює не так, як очікувалося; він копіює лише перші 260 знаків. Ви не можете створити папку, скопіювати / перемістити / відкрити файл ... Змусити мене замислитися, у чому сенс цієї зміни.
raymai97

Зауважте, що твердження про те, що налаштування системи не залежить від налаштування маніфесту, є помилковим. Обоє потрібно. Політику потрібно активувати на системному рівні, а маніфест повинен заявляти, що програма знає довгий шлях.
Ерик Нд

Я читав, що внесення цих змін може спричинити проблеми сумісності зі старими 32-бітовими програмами, але чи є такий тип проблем із сумісністю? Я хотів би змінити сам. lifehacker.com/…
КДП

32

Ви можете змонтувати папку як диск. У командному рядку, якщо у вас є шлях, C:\path\to\long\folderви можете зіставити його для перенесення букви X:за допомогою:

subst x: \path\to\long\folder

я отримую "Недійсний параметр j:" при спробі цієї команди
barrypicker

Це потрібно запустити з командного рядка Адміністратора (підвищеного).
Mrchief

Це не вдасться при нахилах вперед, потрібно мати зворотні риски.
Камберлен

1
Я не впевнений, чи стосується це лише Windows 10, однак я просто виявив, що при спробі запуску цієї команди, якщо я запускаюсь як адміністратор, як запропоновано вище, накопичувач, здається, не є доступним. Це пояснюється тим, що поведінка схожа на відображення мережевого накопичувача і стосується конкретного сеансу тощо, тож коли я запустився як адміністратор і використав цю команду, цей сеанс міг би використовувати x: TL; DR Якщо ви не можете побачити диск, спробуйте виконання команди, не перебуваючи в режимі адміністратора.
Джадді

substце локальна сесія / акаунт - див. superuser.com/questions/29072/… про те, як зробити її "системою широкої"
користувач2864740

18

Один із способів впоратися з межею шляху - скоротити записи шляху символічними посиланнями.

Наприклад:

  1. створити C:\pкаталог для збереження коротких посилань на довгі шляхи
  2. mklink /J C:\p\foo C:\Some\Crazy\Long\Path\foo
  3. додайте C:\p\fooдо свого шляху замість довгого шляху

3
Спочатку не потрібно було створювати каталог, тому крок 1 не є необхідним.
ohaal

2
Цей трюк не завжди працює, оскільки багато програм намагаються вирішити посилання
nponeccop

/jОпція створює спаяний для монтування локального пристрою томи або шлях на локальному томі (як Unix BIND монтування). Це не створює символічного зв’язку. Це важлива відмінність, оскільки точки з'єднання місцевості завжди оцінюються на сервері і повинні орієнтуватися на локальні пристрої, тоді як символьні посилання оцінюються на клієнті і можуть орієнтуватися на віддалені шляхи (якщо це дозволяє політика). Як і привід subst.exe (тобто DefineDosDeviceW), ціль переходу зазвичай обмежена приблизно 4 К символами. Це насправді 8К символів, розподілених приблизно рівномірно між замінним контуром та контуром відображення.
Ерік

12

Можна ввімкнути довгі імена шляху за допомогою PowerShell:

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

Інша версія полягає в використанні групової політики Computer Configuration/ Administrative Templates/ System/ Filesystem:

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


2
Кожна програма все-таки повинна заявити, що вона відома на дальньому шляху. Корпорація Майкрософт зробила погану роботу, передавши це, зробивши вигляд, що маніфест програми є лише іншим способом включити цю функцію, а не чітко пояснюючи, що це договір між ОС (політикою на системному рівні) та програмою, в якій обидва повинні погодитися.
Ерик Нд

8

Щодо того, чому це все ще існує - MS не вважає це пріоритетом, а цінує зворотну сумісність над просуненням своєї ОС (принаймні в цьому випадку).

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


1
Короткі імена шляху можна відключити в реєстрі (чи це була сама файлова система?), Тож це насправді не є надійним вирішенням.
rubenvb

3
@rubenvb Я впевнений, що більшість, якщо не всі функції Windows можуть бути відключені в реєстрі, так що ¯ \ _ (ツ) _ / ¯
Конрад

Генерування коротких імен може бути вимкнено для NTFS (і повинно бути, оскільки воно є неефективним у багатьох випадках), як для всієї системи, так і для тома, тому це ненадійний підхід навіть для шляхів на системному диску, який повинен бути NTFS. Вручну можна встановити короткі імена для файлів і каталогів у NTFS, але це не поширюється на новіші файлові системи, які взагалі не підтримують короткі імена, наприклад, exFAT та ReFS. Короткі імена слід вважати застарілою функцією, яка зберігається для сумісності в обмежених випадках, як-от старий API ANSI / OEM, що використовує одно- та двобайтові кодові сторінки.
Ерик Нд

@eryksun Перегляньте попередній коментар щодо відключення імен коротких шляхів. :) Тільки тому, що ви вважаєте, що це слід вважати застарілим, не означає, що воно є насправді. MS не планує застарівати цю функцію. (Крім того, чому ви встановлюєте програмне забезпечення Windows на розділи exFAT / ReFS?)
Конрад

Я все ще кажу лише використовувати ненормовані шляхи до пристрою (тобто префікс "\\? \"), Оскільки вони завжди доступні і очевидні. Наприклад, перекладіть PATHі передайте його SearchPathW. Це також ефективно, оскільки бібліотека часу виконання в будь-якому випадку створює "\\? \" Шляхи пристрою для NT. Що стосується новіших файлових систем, ми, мабуть, не побачили б програмне забезпечення, встановлене на томі exFAT, окрім портативних програм, оскільки воно не має захисту, але я не виключаю ReFS. Користувачі встановлюють програми в нестандартних місцях з міркувань зручності, простору або продуктивності.
Ерік Нд

7

Щодо того, як впоратися з обмеженням розміру шляху в Windows - використання 7zip для упаковки (і розпакування) файлів, чутливих до довжини шляху, виглядає як життєздатне рішення. Я використовував його для транспортування декількох установок IDE (ті шляхи плагінів Eclipse, витівки!) Та купи автогенерованої документації, і до цього часу не було жодної проблеми.

Не дуже впевнений, як це ухиляється від ліміту 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 символів.

ВАЖЛИВА ПРИМІТКА. Щоб правильно функціонувати, вам потрібно буде вказати шлях призначення у діалоговому вікні "Витяг" 7zip безпосередньо, а не перетягувати файли в потрібну папку. В іншому випадку папка "Темп" буде використовуватися як проміжний кеш, і ви підскочите до того ж обмеження на 260 знаків, як тільки Провідник Windows почне переміщати файли в "остаточне місце спокою". Дивіться відповіді на це запитання для отримання додаткової інформації.


3
Я помилявся, 7zip і WinRAR роблять витяг усіх папок і файлів. Просто властивість папки в Windows повідомляє лише про кількість папок і файлів, які не порушують обмеження. Це так, ніби провідник Windows не копає глибше, щоб відкрити папки, коли буде досягнуто максимального шляху.
Скручений Шепіт

Можна видалити довгий шлях у 7-zip з shift-del.
Лорі Стерн

Коротка відповідь - використовуйте 7zip для розпакування файлу .zip .... працював на мене в Windows 7
andrewcockerham


2

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

Наприклад, він дозволяє копіювати, переміщувати чи перейменувати файли, які навіть Windows Explorer не може. Або, звичайно, розібратися зі вмістом у них, наприклад, md5sum, grep, gzip тощо.

Також для програм, які ви кодуєте, ви можете зв’язати їх із DLL Cygwin, і це дозволить їм використовувати довгі шляхи (я цього не перевіряв)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.