- PVSM.RU - https://www.pvsm.ru -
Пути файловых систем в Windows страннее, чем можно подумать. В любой производной от Unix системе пути на удивление просты: если нечто начинается с /
, то это путь. Но всё совершенно иначе в Windows, которая имеет озадачивающее разнообразие схем составления пути.
Когда я реализовал функцию автозавершения пути в Fileside 1.7 [1], мне нужно было изучить этот вопрос внимательнее, чтобы ничего не упустить. В этой статье я расскажу о своих находках.
Стоит заметить, что статья ограничивается только тем типом путей, который видит пользователь приложений Windows (обусловленный Win32 API). Под этим слоем есть ещё больше любопытного, в основном касающегося тех, кто пишет драйверы оборудования и тому подобное.
Название | Пример |
---|---|
Путь к диску | C:Program FilesHAL 9000 |
UNC-путь | \MediaPicturesWorth1000 words |
Путь к устройству (литеральный) | \?D:PlansMarshall |
Путь к устройству (нормализованный) | \.D:ProjectsHuman Genome |
Название | Примеры |
---|---|
Относительный к текущей папке | .Manhattan , ..Plans |
Относительный к текущему диску | Pacts |
Относительный к текущей папке диска | D:Warsaw |
Символы | Валидность |
---|---|
< > ” / |? * | Никогда не допускаются |
. | Не допускается в качестве последнего символа |
: | Не допускается, за исключением потоков данных |
Элемент | Максимальная длина |
---|---|
Путь | 32767 (или 260) символов |
Имя файла или папки | 255 символов |
В Windows существует три разных вида абсолютного пути и три разных типа относительного пути.
Абсолютные, или полные пути — это завершённые пути, сами по себе уникальным образом идентифицирующие местоположение в файловой системе.
Пути к диску — это старые добрые пути, которые мы знаем и любим, они состоят из буквы диска и последовательности папок.
D:Doughnut preferencesWith jam in
UNC расшифровывается как Universal Naming Convention, это описание файлов, начинающееся с \
, часто используемое для ссылок на сетевые накопители. Первый сегмент после \
— это хост, который может быть или сервером с именем, или IP-адресом:
\WorkHard \192.168.1.15Hard
UNC-пути также можно использовать для доступа к локальным дискам:
\localhostC$UsersAndrew Fletcher \127.0.0.1C$UsersAlan Wilder
Или с использованием имени компьютера:
\PipelineC$UsersMartin Gore
Символ $
в C$
обозначает скрытую административную общую папку [2]; он не заменяет двоеточие рядом с именем диска :
. Общие диски в стиле C$
— это просто удобные ярлыки, автоматически создаваемые Windows. Доступ к дискам через них возможен, только если вы вошли как администратор.
Стоит также заметить, что \Pipeline
сам по себе не валидный путь к папке, он идентифицирует только сервер. Чтобы попасть в папку, нужно добавить имя общей папки.
Путь к устройству начинается с одного из следующих фрагментов:
\?
\.
Кроме файлов и папок их можно использовать для адресации физических устройств (дисков, дисплеев, принтеров и так далее). Не совсем то, что вы используете в повседневном процессе управления файлами, но это полезно знать, если вы когда-нибудь найдёте что-то подобное.
Синтаксис доступа к локальной папке выглядит как один из этих вариантов:
\?Z:AnimalsCute \.Z:AnimalsCunning
Если вам нужно ещё больше загадочности, то можно также подставить эквивалентный Z:
идентификатор устройства:
\?Volume{59e01a55-88c5-411f-bf0b-92820bdb2548}AnimalsCryptic
Здесь Volume{59e01a55-88c5-411e-bf0a-92820bdb2549}
— это идентификатор дискового тома, на котором находится Z:
в компьютере.
Также существует специальный синтаксис для описания UNC-путей как путей к устройству:
\?UNClocalhostZ$AnimalsCurious
В путях к устройству часть, идущая после \?
или \.
— это имя, определённое во внутреннем пространстве имён Object Manager [3] Windows. Те, кому любопытно исследовать это пространство имён, могут скачать инструмент WinObj [4] и посмотреть.
Так в чём же разница между \?
и \.
?
В обычном случае, когда вы передаёте путь операционной системе Windows, она очищает его, прежде чем использовать. Этот процесс называется нормализацией, подробнее о нём мы поговорим ниже.
Путь \?
пропускает этот этап очистки, а \.
не пропускает. Поэтому можно назвать пути \?
литеральными путями к устройству, а \.
— нормализованными путями к устройству.
Допустим, по какой-то непонятной причине, у вас есть файл с именем ..
(например, он мог быть создан на сетевом диске в другой системе). В обычном случае вы бы не смогли получить доступ к нему, потому что нормализация резолвит его в родительскую папку, но благодаря литеральному пути к устройству это можно сделать.
Относительные пути — это неполные пути, которые для уникальной идентификации местоположения необходимо скомбинировать с другим путём.
Эти пути используют в качестве начальной точки текущую папку, например, .Torquay
относится к подпапке текущей папки, а ..Wales
относится к подпапке родителя текущей папки.
Если начать путь с одной , то путь интерпретируется как относительный к корню текущего диска. Поэтому если вы находитесь в любом месте диска
E:
и введёте Africa
, то окажетесь в E:Africa
.
Когда доступ к текущей папке выполняется через UNC-путь, то путь, относительный к текущему диску, интерпретируется относительно к общей корневой папке, допустим \EarthAsia
.
Эти более редко используемые пути указывают диск без обратной косой черты, например E:Kreuzberg
, и интерпретируются относительно к текущей папке этого накопителя. На самом деле это имеет смысл только в контексте оболочки командной строки, отслеживающей текущую рабочую папку для каждого диска.
Это единственный тип путей, не поддерживаемый Fileside, потому что в нём нет понятия текущей папки каждого диска. Текущую папку имеют только панели.
Как говорилось ранее, все пути, за исключением литеральных путей к устройству, перед использованием проходят процесс нормализации. Этот процесс состоит из следующих этапов:
/
) на обратные косые черты (
).
или ..
Таким образом, в общем случае можно указывать пути Windows при помощи косых черт.
Теперь рассмотрим отдельные элементы, из которых состоит путь. Существует множество ограничений имён, которые можно использовать для файлов и папок.
В имени нельзя использовать следующие символы:
< > " / | ? *
Также исключаются любые непечатаемые символы со значением ASCII меньше 32 [5].
В большинстве случаев :
также запрещено.
Однако существует экзотическое исключение в виде изменённых потоков данных NTFS, в которых двоеточие используется в качестве разделителя внутри имени. Малоизвестно, что в некоторых контекстах можно хранить внутри файла скрытый фрагмент данных [6], добавляя к его имени суффикс, которому предшествует двоеточие.
Символ .
допустим внутри или в начале имени, но запрещён в конце.
Любопытно, что Windows допускает пробелы в начале, но не в конце имён. Так как имя с пробелами в начале и конце часто выглядит похожим на имя без пробелов, обычно это ужасная идея, и при переименовании или создании файлов Fileside автоматически удаляет их.
По историческим причинам нельзя использовать следующие имена:
CON
, PRN
, AUX
, NUL
, COM0
, COM1
, COM2
, COM3
, COM4
, COM5
, COM6
, COM7
, COM8
, COM9
, LPT0
, LPT1
, LPT2
, LPT3
, LPT4
, LPT5
, LPT6
, LPT7
, LPT8
и LPT9
.
Это включает и имена с расширениями. Например, если вы назовёте файл COM1.txt
, то внутри он преобразуется в \.COM1
и интерпретируется самой Windows как устройство. А это не то, что нам нужно.
В большинстве случаев Windows не делает различий между символами в верхнем и нижнем регистре в путях.
C:Polish hamlet
, c:polish Hamlet
, C:Polish Hamlet
и C:POliSh hAMlET
считаются абсолютно одинаковыми.
Однако с обновления Windows 10 за апрель 2018 года файловые системы NTFS имеют опцию включения чувствительности к регистру на уровне папок [7].
Мы ещё не закончили: ограничения есть и на длину.
Традиционно длина пути в Windows не могла превышать 260 символов [8]. Даже сегодня это справедливо для некоторых приложений, если только их разработчики не предприняли мер для обхода этого ограничения.
Этот обход заключается в преобразовании каждого пути в литеральный путь к устройству перед передачей его Windows. Сделав это, мы сможем обойти ограничение в 260 символов и увеличить его до чуть более щедрого предела в 32767 символов.
Имена файлов и папок не могут быть длиннее 255 символов.
Вооружённые этим знанием, мы понимаем, что можем создать почти неограниченное количество различных строк путей, и все они будут ссылаться на одну и ту же папку.
C:CHAMELEON
c:chameleon
C:/\//\///Chameleon
C:Windows..Users..Chameleon
\localhostC$Chameleon
\127.0.0.1C$Chameleon
\?C:Chameleon
\.C:Chameleon
\.UNClocalhostC$Chameleon
\?Volume{59e01a55-88c5-411e-bf0a-92820bdb2549}Chameleon
\.GLOBALROOTDeviceHarddiskVolume4Chameleon
Вот что получаешь, когда приходится обеспечивать полную обратную совместимость в течение нескольких десятилетий!
Автор:
PatientZero
Источник [9]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/windows/384361
Ссылки в тексте:
[1] функцию автозавершения пути в Fileside 1.7: https://www.fileside.app/blog/2023-03-02_release-notes-1.7.0/#auto-completion-for-typed-paths
[2] административную общую папку: https://learn.microsoft.com/en-us/troubleshoot/windows-server/networking/remove-administrative-shares#introduction
[3] Object Manager: https://en.wikipedia.org/wiki/Object_Manager_(Windows)
[4] WinObj: https://learn.microsoft.com/en-us/sysinternals/downloads/winobj
[5] значением ASCII меньше 32: https://www.asciitable.com/
[6] хранить внутри файла скрытый фрагмент данных: https://blog.netwrix.com/2022/12/16/alternate_data_stream/
[7] включения чувствительности к регистру на уровне папок: https://www.howtogeek.com/354220/how-to-enable-case-sensitive-folders-on-windows-10/
[8] длина пути в Windows не могла превышать 260 символов: https://learn.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation?tabs=registry
[9] Источник: https://habr.com/ru/articles/731628/?utm_source=habrahabr&utm_medium=rss&utm_campaign=731628
Нажмите здесь для печати.