Пути файловых систем в Windows страннее, чем можно подумать. В любой производной от Unix системе пути на удивление просты: если нечто начинается с
/, то это путь. Но всё совершенно иначе в Windows, которая имеет озадачивающее разнообразие схем составления пути.Когда я реализовал
функцию автозавершения пути в Fileside 1.7, мне нужно было изучить этот вопрос внимательнее, чтобы ничего не упустить. В этой статье я расскажу о своих находках.Стоит заметить, что статья ограничивается только тем типом путей, который видит пользователь приложений Windows (обусловленный Win32 API). Под этим слоем есть
ещё больше любопытного, в основном касающегося тех, кто пишет драйверы оборудования и тому подобное.
Вкратце
Форматы абсолютных путей
Форматы относительных путей
Запрещённые символы
Ограничения длины
Схемы путей Windows
В Windows существует три разных вида абсолютного пути и три разных типа относительного пути.
Абсолютные пути
Абсолютные, или полные пути — это завершённые пути, сами по себе уникальным образом идентифицирующие местоположение в файловой системе.
Пути к диску
Пути к диску — это старые добрые пути, которые мы знаем и любим, они состоят из буквы диска и последовательности папок.
D:\Doughnut preferences\With jam in
UNC-пути
UNC расшифровывается как Universal Naming Convention, это описание файлов, начинающееся с
\\, часто используемое для ссылок на сетевые накопители. Первый сегмент после
\\ — это хост, который может быть или сервером с именем, или IP-адресом:
\\Work\Hard
\\192.168.1.15\Hard
UNC-пути также можно использовать для доступа к локальным дискам:
\\localhost\C$\Users\Andrew Fletcher
\\127.0.0.1\C$\Users\Alan Wilder
Или с использованием имени компьютера:
\\Pipeline\C$\Users\Martin Gore
Символ
$ в
C$ обозначает скрытую
административную общую папку; он не заменяет двоеточие рядом с именем диска
:. Общие диски в стиле
C$ — это просто удобные ярлыки, автоматически создаваемые Windows. Доступ к дискам через них возможен, только если вы вошли как администратор.Стоит также заметить, что
\\Pipeline сам по себе не валидный путь к папке, он идентифицирует только сервер. Чтобы попасть в папку, нужно добавить имя общей папки.
Пути к устройству
Путь к устройству начинается с одного из следующих фрагментов:
Кроме файлов и папок их можно использовать для адресации физических устройств (дисков, дисплеев, принтеров и так далее). Не совсем то, что вы используете в повседневном процессе управления файлами, но это полезно знать, если вы когда-нибудь найдёте что-то подобное.Синтаксис доступа к локальной папке выглядит как один из этих вариантов:
\\?\Z:\Animals\Cute
\\.\Z:\Animals\Cunning
Если вам нужно ещё больше загадочности, то можно также подставить эквивалентный
Z: идентификатор устройства:
\\?\Volume{59e01a55-88c5-411f-bf0b-92820bdb2548}\Animals\Cryptic
Здесь
Volume{59e01a55-88c5-411e-bf0a-92820bdb2549} — это идентификатор дискового тома, на котором находится
Z: в компьютере.Также существует специальный синтаксис для описания UNC-путей как путей к устройству:
\\?\UNC\localhost\Z$\Animals\Curious
В путях к устройству часть, идущая после
\\?\ или
\\.\ — это имя, определённое во внутреннем пространстве имён
Object Manager Windows. Те, кому любопытно исследовать это пространство имён, могут скачать инструмент
WinObj и посмотреть.
Нормализованные и литеральные пути к устройству
Так в чём же разница между
\\?\ и
\\.\?В обычном случае, когда вы передаёте путь операционной системе Windows, она очищает его, прежде чем использовать. Этот процесс называется
нормализацией, подробнее о нём мы поговорим ниже.Путь
\\?\ пропускает этот этап очистки, а
\\.\ не пропускает. Поэтому можно назвать пути
\\?\ литеральными путями к устройству, а
\\.\ —
нормализованными путями к устройству.Допустим, по какой-то непонятной причине, у вас есть файл с именем
.. (например, он мог быть создан на сетевом диске в другой системе). В обычном случае вы бы не смогли получить доступ к нему, потому что нормализация резолвит его в родительскую папку, но благодаря литеральному пути к устройству это можно сделать.
Относительные пути
Относительные пути — это неполные пути, которые для уникальной идентификации местоположения необходимо скомбинировать с другим путём.
Пути, относительные к текущей папке
Эти пути используют в качестве начальной точки текущую папку, например,
.\Torquay относится к подпапке текущей папки, а
..\Wales относится к подпапке родителя текущей папки.
Папки, относительные к корню текущего диска
Если начать путь с одной
\, то путь интерпретируется как относительный к корню текущего диска. Поэтому если вы находитесь в любом месте диска
E: и введёте
\Africa, то окажетесь в
E:\Africa.Когда доступ к текущей папке выполняется через UNC-путь, то путь, относительный к текущему диску, интерпретируется относительно к общей корневой папке, допустим
\\Earth\Asia.
Пути, относительные к текущей папке диска
Эти более редко используемые пути указывают диск без обратной косой черты, например
E:Kreuzberg, и интерпретируются относительно к текущей папке этого накопителя. На самом деле это имеет смысл только в контексте оболочки командной строки, отслеживающей текущую рабочую папку для каждого диска.Это единственный тип путей, не поддерживаемый Fileside, потому что в нём нет понятия текущей папки каждого диска. Текущую папку имеют только панели.
Нормализация
Как говорилось ранее, все пути, за исключением литеральных путей к устройству, перед использованием проходят процесс нормализации. Этот процесс состоит из следующих этапов:
- Замена косых черт (
/) на обратные косые черты (\) - Сворачивание повторяющихся разделителей в виде обратных косых черт в один
- Резолвинг относительных путей заменой всех
. или .. - Отсечение завершающих пробелов и точек
Таким образом, в общем случае можно указывать пути Windows при помощи косых черт.
Правила именования в Windows
Теперь рассмотрим отдельные элементы, из которых состоит путь. Существует множество ограничений имён, которые можно использовать для файлов и папок.
Запрещённые символы
В имени нельзя использовать следующие символы:
< > " / \ | ? *
Также исключаются любые непечатаемые символы со
значением ASCII меньше 32.
Хитрое двоеточие
В большинстве случаев
: также запрещено.Однако существует экзотическое исключение в виде изменённых потоков данных NTFS, в которых двоеточие используется в качестве разделителя внутри имени. Малоизвестно, что в некоторых контекстах можно
хранить внутри файла скрытый фрагмент данных, добавляя к его имени суффикс, которому предшествует двоеточие.
Опасная точка
Символ
. допустим внутри или в начале имени, но запрещён в конце.
Начинающие и завершающие пробелы
Любопытно, что 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 имеют опцию
включения чувствительности к регистру на уровне папок.
Ограничения длины
Мы ещё не закончили: ограничения есть и на длину.
Пути
Традиционно
длина пути в Windows не могла превышать 260 символов. Даже сегодня это справедливо для некоторых приложений, если только их разработчики не предприняли мер для обхода этого ограничения.Этот обход заключается в преобразовании каждого пути в литеральный путь к устройству перед передачей его Windows. Сделав это, мы сможем обойти ограничение в 260 символов и увеличить его до чуть более щедрого предела в 32767 символов.
Имена
Имена файлов и папок не могут быть длиннее 255 символов.
Так много способов сказать одно и то же
Вооружённые этим знанием, мы понимаем, что можем создать почти неограниченное количество различных строк путей, и все они будут ссылаться на одну и ту же папку.
C:\CHAMELEONc:\chameleonC:\/\\//\\\///ChameleonC:\Windows\..\Users\..\Chameleon\\localhost\C$\Chameleon\\127.0.0.1\C$\Chameleon\\?\C:\Chameleon\\.\C:\Chameleon\\.\UNC\localhost\C$\Chameleon\\?\Volume{59e01a55-88c5-411e-bf0a-92820bdb2549}\Chameleon\\.\GLOBALROOT\Device\HarddiskVolume4\Chameleon- и так далее
Вот что получаешь, когда приходится обеспечивать полную обратную совместимость в течение нескольких десятилетий!