Катало́г (также директо́рия; ) — объект файловой системы, содержащий записи, которые связывают имена с ами и другими каталогами. В иерархических файловых системах каталоги могут содержать другие каталоги, образуя структуру с корневым каталогом во главе; положение файла или каталога в ней задаётся путём. В графических интерфейсах каталоги обычно представлены как папки. В Windows «папками» называют также объекты оболочки, не являющиеся каталогами файловой системы.
История
В файловых системах с одноуровневой организацией все файлы находятся в одном каталоге. Такая схема проста, но при большом числе файлов становится неудобной: все они оказываются в одном списке, а сгруппировать связанные файлы по отдельным каталогам нельзя. Иерархическая система позволяет распределять файлы по каталогам, которые могут быть вложены друг в друга.
В рамках проекта Multics была разработана файловая система с иерархией каталогов произвольной глубины. Каталог мог содержать как файлы, так и другие каталоги; одно и то же имя могло использоваться в разных каталогах, а местоположение файла определялось его путём относительно текущего каталога или корня. Её устройство описали Роберт Дейли и Питер Нейман в 1965 году.
Иерархическая файловая система стала одной из характерных особенностей Unix. Каталог в ней представляет собой файл особого типа, записи которого связывают имена с файлами. Файловые системы отдельных устройств можно подключать к существующему дереву каталогов, включая их в общую иерархию.
На персональных компьютерах иерархические каталоги распространились позднее. В CP/M 2.2 подкаталогов не было: файлы разделялись между пронумерованными пользовательскими областями. MS-DOS 1.x также поддерживала только один каталог на каждом диске. С появлением IBM PC/XT с жёстким диском ёмкостью 10 МБ такая организация стала неудобной. В MS-DOS 2.0, выпущенной в марте 1983 года, появились корневой каталог и вложенные подкаталоги; при проектировании этой структуры разработчики ориентировались на Xenix — систему Microsoft на основе Unix.
Схожий переход произошёл на компьютерах Macintosh. MFS, использовавшаяся на первых Macintosh, была плоской файловой системой: все файлы тома находились в одном каталоге, а отображаемая пользователю вложенность папок поддерживалась системным программным обеспечением. В пришедшей ей на смену HFS каталоги стали частью структуры файловой системы и могли содержать файлы и другие каталоги.
Иерархия и пути
В иерархической файловой системе каталоги обычно образуют дерево. Его верхний уровень называется корневым каталогом. В Unix-подобных системах корневой каталог обозначается символом /. В Windows каждый том имеет собственный корневой каталог; если тому назначена буква диска, он может обозначаться, например, как C:\.
Чтобы указать файл или каталог, используют путь — последовательность имён, по которой файловая система переходит от одного каталога к другому. В Unix-подобных системах компоненты пути разделяются символом /. Путь, начинающийся с /, называется абсолютным и отсчитывается от корневого каталога; остальные пути являются относительными и отсчитываются от текущего каталога. В Windows в качестве разделителя обычно используется обратная косая черта \; путь вида C:\Users\Public начинается от корня соответствующего тома.
Специальные компоненты . и .. обозначают соответственно текущий и родительский каталоги. Например, путь ../photo.jpg указывает на файл photo.jpg в родительском каталоге.
Символьная ссылка — файл особого типа, содержащий путь к другому объекту файловой системы. Она может указывать в том числе на каталог; при разрешении пути система подставляет хранящийся в ссылке путь и продолжает поиск. Поэтому компонент .. после перехода по символической ссылке относится к родительскому каталогу её цели, а не к каталогу, в котором находится сама ссылка. Файловая иерархия в целом не сводится к простому дереву: один файл может иметь несколько имён, а символические ссылки могут указывать на каталоги в других частях иерархии, в том числе на вышестоящие. Такие ссылки могут образовывать циклы; если при разрешении пути обнаружен цикл, операция завершается ошибкой [ELOOP]. В Windows для каталогов используются как символические ссылки, так и точки соединения (); точки соединения указывают только на каталоги и могут вести, в частности, к каталогу на другом локальном томе.
Иерархия каталогов не единственный способ организации файлов: их можно группировать и находить по метаданным. В Be File System (BFS), разработанной для BeOS и позднее реализованной в Haiku, файлам можно присваивать дополнительные атрибуты, индексировать их и выполнять запросы по значениям этих атрибутов. Например, почтовые сообщения могут отбираться по отправителю или теме. В macOS файловый менеджер Finder позволяет присвоить файлу или каталогу несколько тегов, а затем искать, сортировать и группировать объекты по этим тегам. Такие механизмы дополняют иерархию каталогов, позволяя находить и объединять объекты по их свойствам независимо от каталога, в котором они находятся.
Имена и ограничения
Имя файла или каталога является одним компонентом пути. Допустимые символы и максимальная длина имени зависят от операционной системы и файловой системы. В POSIX максимальная длина отдельного компонента обозначается NAME_MAX, а длина пути — PATH_MAX; соответствующие ограничения могут зависеть от пути и могут быть получены программой с помощью pathconf().
POSIX определяет переносимый набор символов для имён: латинские буквы, цифры, точку, дефис и подчёркивание. Символ / не может входить в имя, поскольку разделяет компоненты пути; нулевой байт также не может быть частью имени.
В Windows в именах файлов и каталогов нельзя использовать символы <, >, :, ", /, \, |, ? и *, а также управляющие символы с кодами от 1 до 31. Зарезервированы также имена устройств, в том числе CON, NUL, COM1 и LPT1; эти ограничения распространяются и на имена каталогов.
В Windows API традиционно действует ограничение MAX_PATH длиной 260 символов. Начиная с Windows 10 версии 1607 многие файловые функции могут работать без этого ограничения, если оно включено в системе и приложение объявляет поддержку длинных путей. Для поддерживающих расширенные пути функций префикс \\?\ также позволяет использовать пути длиннее обычного предела MAX_PATH.
Правила сравнения имён по регистру зависят от системы и файловой системы. В Unix-подобных файловых системах имена, как правило, чувствительны к регистру: file и File могут обозначать разные объекты. В Windows имена обычно сравниваются без учёта регистра, хотя исходный регистр сохраняется. Для каталогов на NTFS современные версии Windows поддерживают отдельный флаг чувствительности к регистру, используемый в том числе при работе с WSL.
Операции над каталогами
Каталог нельзя изменить, записав в него данные, как в обычный файл: в Unix-подобных системах попытка открыть каталог на запись завершается ошибкой [EISDIR]. Его содержимое изменяется специальными операциями, которые создают, удаляют или переименовывают записи каталога. Такие операции по стандарту выполняются атомарно: каждая либо полностью применяется, либо не изменяет файловую систему.
По POSIX новый каталог создаётся вызовом mkdir() пустым; специальные имена . и .. обозначают соответственно сам каталог и его родительский каталог. Удалить каталог вызовом rmdir() можно, только если он пуст. Рекурсивное удаление дерева каталогов выполняется обходом его содержимого: например, rm -r удаляет объекты последовательно. В Windows API тем же операциям соответствуют CreateDirectory и RemoveDirectory; последняя также требует, чтобы каталог был пуст.
Чтобы получить содержимое каталога, его открывают и последовательно читают записи. Интерфейсы не обязаны возвращать их в алфавитном порядке, поэтому при необходимости сортировку выполняет программа, которая выводит список. В POSIX для этого служат opendir() и readdir(), а в Windows API — FindFirstFile и FindNextFile.
В пределах одной файловой системы переименование и перемещение выполняются одной операцией: rename() меняет имя записи, каталог, в котором она находится, или и то и другое. Содержимое файла при этом копировать не требуется. Если исходный и новый путь находятся в разных файловых системах, rename() может завершиться ошибкой [EXDEV]; mv в этом случае копирует объект в новое место и после успешного копирования удаляет исходный.
Устройство каталога
В модели POSIX каталог содержит записи, связывающие имена с файлами. Имя относится к записи каталога, тогда как основные свойства файла — например, размер, временные метки и права доступа — относятся к самому файлу. Поэтому несколько записей каталога могут указывать на один и тот же файл: так образуются жёсткие ссылки. Конкретное устройство каталога зависит от файловой системы.
Простейший способ найти нужное имя — последовательно просмотреть записи каталога. С ростом числа записей такой поиск замедляется, поэтому для ускорения поиска могут использоваться индексы и другие структуры данных.
В файловых системах FAT каталог представляет собой последовательность 32-байтовых записей. В FAT12 и FAT16 корневой каталог является особым случаем: он расположен в фиксированном месте непосредственно после таблиц FAT, а его размер задаётся при форматировании полем BPB_RootEntCnt и впоследствии не меняется. Поэтому число записей в корневом каталоге ограничено, даже если в области данных остаётся свободное место. В FAT32 корневой каталог хранится как цепочка кластеров, подобно остальным каталогам, и может увеличиваться по мере необходимости.
В ext4 запись каталога содержит имя и номер соответствующего индексного дескриптора, в котором хранятся основные метаданные файла. В неиндексированном каталоге записи располагаются последовательно в блоках; индексированные каталоги используют структуру htree, в которой хеш имени помогает определить блок с нужной записью. Каталог содержит также записи . и .., указывающие соответственно на него самого и родительский каталог.
В NTFS сведения о файлах и каталогах хранятся в главной файловой таблице (MFT); одному файлу может соответствовать одна или несколько записей MFT. Содержимое каталога организовано как индекс имён со структурой B-дерева. Корень индекса хранится в атрибуте $INDEX_ROOT; для крупных каталогов используется также $INDEX_ALLOCATION.
Права доступа
В Unix-подобных системах к каталогам применяются те же три права доступа, что и к обычным файлам, но означают они другое: каталог содержит имена, поэтому права определяют, что можно делать с именами, а не с данными файлов.
Право чтения (r) позволяет получить список имён в каталоге, а право поиска (x) — обратиться по известному имени к находящемуся в нём объекту; при разборе пути право поиска необходимо для каждого каталога на этом пути. Эти права независимы: имея x без r, можно обратиться к объекту с заранее известным именем, если это позволяют права самого объекта, но нельзя получить список имён в каталоге; имея r без x, наоборот, можно перечислить имена, но нельзя обратиться по ним к соответствующим объектам.
Право записи (w) позволяет изменять записи каталога — создавать, удалять и переименовывать имена; для таких операций требуется также право поиска (x). Оно не даёт права изменять содержимое самих файлов — это определяется их собственными правами. И наоборот, право записи на сам файл для его удаления не требуется: необходимы право записи на содержащий его каталог и право поиска по пути.
Поскольку удаление файла определяется правами на каталог, в каталогах, доступных для записи многим пользователям, любой из них мог бы удалять чужие файлы. Для таких каталогов предусмотрен sticky bit (S_ISVTX): при нём удалять и переименовывать файлы в каталоге могут владелец файла, владелец каталога и процессы с соответствующими привилегиями; разрешено ли это также пользователям, имеющим право записи на сам файл, зависит от реализации.