Я пытаюсь понять, какова максимально допустимая длина пути к файлу.
Для этого я использую стандартный файловый менеджер Windows (в Windows 7) и следующий скрипт PowerShell:
Get-ChildItem | Select Name, FullName, @{N="Path Length";E={$_.FullName.Length}} | Format-List
Я открываю менеджер, создаю файл abc.txt
в C:\
, а затем добавляю буквы в abc
столько, сколько позволяет файловый менеджер. (На самом деле, я, конечно, использую копирование и вставку. Это намного быстрее.)
Затем я провожу тот же тест в C:\aaa
и C:\aaa\bbb
.
По какой-то причине результаты разные. Максимальная длина в C:\aaa
и C:\aaa\bbb
составляет 259 символов, а максимальная длина в C:\
составляет 258 символов. Почему?
C:\abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz_abcdefgh.txt
258 characters
C:\aaa\abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz_abcde.txt
259 characters
C:\aaa\bbb\abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz_a.txt
259 characters
обновлять
Список Python с mail-archive.com:
(https://www.mail-archive.com/[email protected]/msg444514.html)
классические ограничения длины пути DOS (например, 247, 258 или 259 символов в зависимости от контекста).
Приведенные ниже пояснения принадлежат мне.
247 обозначает максимальную длину пути к каталогу: 260 - 12 - 1 = 247. Здесь 12 обозначает имя файла 8.3, а 1 обозначает терминатор NUL. Например, C:\foo
илиC:\foo\bar
259 обозначает максимальную длину путифайл(не каталог) располагаетсянетв корне диска. Например,C:\foo\aaa.txt
258 обозначает максимальную длину путифайл(не каталог) располагаетсявкорень диска. Например,C:\aaa.txt
Таким образом, на самом деле существует три предела: 247, 258 и 259.
Но почему у нас ограничение в 258 файлов в корне диска и 259 файлов в других каталогах?
Смотрите также:https://www.mail-archive.com/[email protected]/msg106171.html
MAX_PATH, который ограничивает длину пути к файлам всего 259 символами (без завершающего нуля); длину текущего каталога — 258 символами (без завершающей обратной косой черты и нуля); а длину пути к новому каталогу — 247 символами (вычтите 12 из 259, чтобы оставить место для имени файла 8.3).
Однако вторая цитата мне не понятна. Я не могу понять, почему этот парень говорит о завершающем обратном слеше. Завершающий обратный слеш может быть тем случаем, когда мы говорим о каталогах, но не о файлах!
решение1
У меня есть простое объяснение этой разницы: плохой код в Windows 7, переписанный заново в Windows 10. Ниже я покажу, почему я так думаю, и каковы правила относительно длины имен файлов в Windows 7 и 10.
Но сначала небольшое замечание: ограничение в 260 МАКС_ПУТЬ является артефактом гораздо более ранней версии Windows. Его нельзя изменить, поскольку Windows API активно использует его в своих структурах данных, например, в WIN32_FIND_DATA, так что увеличение его в API приведет к переполнению памяти в существующих приложениях. Вот почему длинные имена файлов должны быть явно разрешены в реестр и программа должна объявить в своем манифесте о своей способности обрабатывать длинные имена.
Я также отмечаю, что буква диска ( C:\
) включена только в текст и не относится к таблицам дисков Windows (MFT). Windows хорошо знает, на каком диске находится файл.
Ниже приведены мои тесты в Windows 7, результаты которых подтверждают выводы автора:
Можно вывести следующие правила:
- Буква диска не учитывается при расчете лимита (
C:
) - Начальная обратная косая черта не учитывается в расчетах пределов (
C:\
) - Остальное ограничено 256 символами, включая промежуточные обратные косые черты.
- Длина корневого файла может достигать 255 символов, чего не могут сделать файлы в папках.
Эти бессмысленные результаты однозначно указывают на плохо написанный код.
Для начала, что касается MFT, каждый компонент пути является отдельным и имеет точно такие же ограничения по длине, как и любой другой компонент (подпапка), поэтому нет никаких причин, присущих дисковым таблицам, ограничивать длину имен файлов только потому, что они включены в какую-то папку.
Во-вторых, у нас возникает вопрос, почему корневой файл ограничен 255 символами, когда, казалось бы, он должен быть 256, поскольку это единственный элемент в его пути (который, как мы видели, может достигать 256 символов).
В поисках объяснения я предположил, что 255 — это реальный предел для имен файлов, установленный Microsoft, а все остальное — просто плохо написанный код.
Чтобы проверить эту теорию, я протестировал поведение Windows 10. Я повторил те же операции (для записи в ) (требуются права администратора C:\
):
Как видно выше, поведение здесь гораздо более логично: промежуточные компоненты пути больше не учитываются при ограничении размера имени файла, который всегда составляет 255 символов.
Стало ясно, что изначально Microsoft намеревалась разрешить использовать имена файлов длиной 255 символов, но в Windows 7 это было отключено кодом, учитывающим путь, причем без какой-либо веской причины.
Дальнейшие раскопки обнаружили документацию для NTFS Атрибут - $FILE_NAME (0x30), который указывает один байт для длины имени файла (по смещению 0x40). Это хорошо объясняет ограничение в 255 символов. (См. также FireEye Часть 2: Внутренняя структура атрибута имени файла).
Небольшой анекдот: Согласно закону Microsoft о сохранении ошибок, проводник Windows 10 не смог удалить файлы длиной 255 символов в C:\
, C:\Temp
и C:\Temp\abc
. Мне пришлось ввести в командной строке команду, del 12*
чтобы избавиться от них. (Исправить одну ошибку, одновременно вводя другую...)
решение2
По какой-то причине результаты разные. Максимальная длина в C:\aaa и C:\aaa\bbb составляет 259 символов, но максимальная длина в C:\ составляет 258 символов. Почему?
Думаю, вы спрашиваете, какова максимальная длина пути, обычно допускаемая проводником Windows. 260 символов.
Это позволяет ввести 248 символов для пути и 12 символов для имени файла.
Имена файлов ваших примеров отличаются из-за нулевого символа.
В редакциях Windows до Windows 10 версии 1607 максимальная длина пути составляет MAX_PATH, что определяется как 260 символов. В более поздних версиях Windows для снятия ограничения требуется изменение раздела реестра или использование инструмента групповой политики.
В Windows API (за некоторыми исключениями, обсуждаемыми в следующих параграфах) максимальная длина пути составляет MAX_PATH, что определяется как 260 символов. Локальный путь структурирован в следующем порядке: буква диска, двоеточие, обратная косая черта, компоненты имени, разделенные обратной косой чертой, и завершающий нулевой символ. Например, максимальный путь на диске D — это "D:\some 256-character path string", где "" представляет собой невидимый завершающий нулевой символ для текущей системной кодовой страницы. (Символы < > используются здесь для наглядности и не могут быть частью допустимой строки пути.)
Источник:
решение3
Необходимо учитывать два ограничения: одно — максимальная длина пути, другое — максимальная длина имени файла. В NTFS,Имена файлов могут содержать до 255 кодовых точек UTF-16., без нулевого байта (см. стр. 12).
abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz_abcdefgh.txt
имеет длину ровно 255 символов.