Типы файлов в Linux
Файлы и их индексные дескрипторы (inode)
Каждый файл содержит какие-то данные, но где храниться информация о самом файле? Такую информацию называют метаданными. Метаданные хранятся в файловых дескрипторах, которые называют inod. Разные типы файловых систем работают с метаданными по разному, например ext4 выделяет некоторое место в начале раздела для хранения индексных дескрипторов. У каждого индексного дескриптора есть свой уникальный номер.

Индексный дескриптор хранит следующую информацию:
- свой номер;
- тип файла;
- владельца файла и права доступа к нему;
- время:
- создания файла (crtime);
- доступа к файлу, его ещё называют временем касания (atime);
- последнего изменения файла (mtime);
- последнего изменения метаданных файла (например изменили права доступа к файлу) (ctime:);
- физическое расположение блоков данных на диске.
Чтобы увидеть номера индексных дескрипторов к команде ls добавляют опцию -i:
$ ls -i /etc/ssh/
928146 moduli 928421 ssh_host_dsa_key 933606 ssh_host_ed25519_key.pub
918838 ssh_config 928422 ssh_host_dsa_key.pub 918245 ssh_host_rsa_key
917921 ssh_config.d 928426 ssh_host_ecdsa_key 928420 ssh_host_rsa_key.pub
928412 sshd_config 928427 ssh_host_ecdsa_key.pub 928069 ssh_import_id
928147 sshd_config.d 928428 ssh_host_ed25519_key
- Возле каждого файла написан номер его индексного дескриптора.
Чтобы посмотреть некоторые метаданные файла, можете воспользоваться командой stat:
$ stat /etc/ssh/sshd_config
File: /etc/ssh/sshd_config
Size: 3281 Blocks: 8 IO Block: 4096 regular file
Device: 802h/2050d Inode: 394570 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2022-05-16 08:36:10.592000000 +0000
Modify: 2022-05-13 13:15:09.108000000 +0000
Change: 2022-05-13 13:15:09.108000000 +0000
Birth: 2022-05-13 13:08:03.289339233 +0000
Чтобы стало понятнее я разберу некоторый вывод:
File: /etc/ssh/ssh_config— путь к файлу и его имя;Size: 3281— размер файла в байтах;regular file— тип файла (обычный файл);Inode: 394570— номер индексного дескриптора;Links: 1— количество жестких ссылок;Access: (0644/-rw-r—r—) Uid: ( 0/ root) Gid: ( 0/ root)— владелец и права доступа (это тоже разберём в других статьях);Access:— время последнего доступа к файлу;Modify:— время последнего изменения файла;Change:— время последнего изменения метаданных файла;Birth:— время создания файла (Ubuntu 20.04 — не могла вывести это значение, а 22.04 уже может, как и Debian 11).
В итоге, вы должны запомнить что каждому файлу соответствует какой-то inode. Но чтобы было удобнее обращаться к файлам им ещё придумали имена. Имена файлов, кстати, не находятся в индексных дескрипторах, они находятся в каталогах. А каталоги это тоже файлы, но об этом ниже.
Обычные файлы и каталоги
Мы уже рассматривали вывод команды ls -lh:
Тип файла
| Права
| | Кол-во ссылок
| | | Владелец
| | | | Группа
| | | | | Размер
| | | | | | Дата и время последнего доступа к файлу
| | | | | | | Имя файла
| | | | | | | |
- rw-r--r-- 1 alex alex 0 ноя 26 16:17 file.txt
- Первый символ указывает на тип файла. Пришло время узнать какие типы файлов бывают в Linux. А начнем мы с обычных файлов и каталогов.
На обычные файлы указывает символ тире -. Обычные файлы содержат какие-то данные. Это могут быть файлы изображений, сжатые файлы, текстовые файлы, файлы программ и другое.
Каталоги, это тоже файлы и на них указывает символ d. Они хранят некий список файлов, и это список состоит из строк, в которых записаны имена файлов и их индексные дескрипторы (inode).

Когда мы выполняем команду ls, то мы просто читаем текущий каталог как файл и видим список файлов. Получается что команда ls это как команда cat, но только для каталогов:
$ ls
dir1 file1
$ ls /etc/ssh/
moduli sshd_config.d ssh_host_ecdsa_key.pub ssh_host_rsa_key.pub
ssh_config ssh_host_dsa_key ssh_host_ed25519_key ssh_import_id
ssh_config.d ssh_host_dsa_key.pub ssh_host_ed25519_key.pub
sshd_config ssh_host_ecdsa_key ssh_host_rsa_key
А когда мы в каталоге создаём новый файл, то для него выделяется свободный inode, в каталоге записывается новая строчка с именем этого файла и его индексным дескриптором. Ну и конечно на диск записываются какие-то блоки данных, чтобы физически поместить файл на диск. И когда мы открываем файл, например чтобы его отредактировать, мы по inode находим где этот файл физически лежит на диске. Так каталоги помогают нам обращаться к файлам по их именам.
Раз каталог это тоже файл, то он тоже имеет свой индексный дескриптор. Вот пример просмотра каталога с помощью команды stat:
$ stat dir1
File: dir1
Size: 4096 Blocks: 8 IO Block: 4096 directory
Device: 802h/2050d Inode: 398016 Links: 2
Access: (0775/drwxrwxr-x) Uid: ( 1000/ alex) Gid: ( 1000/ alex)
Access: 2022-05-16 08:43:30.267484822 +0000
Modify: 2022-05-16 08:43:30.267484822 +0000
Change: 2022-05-16 08:43:30.267484822 +0000
Birth: 2022-05-16 08:43:30.267484822 +0000
Тип файла — directory (каталог). Пустой каталог сразу занимает 4096 байт. Но размер каталога не зависит от размера файлов в нем. Например, в каталоге будет 10 файлов по 1 GB, при этом размер каталога останется равным 4096 байт. Размер каталога зависит от количества файлов в нем, ведь каталог это файл содержащий список файлов и чем он больше, тем больше размер каталога.
Например, создадим в нашем каталоге 500 пустых файлов и посмотрим на сколько увеличился размер каталога:
$ touch dir1/file-{001..500}.txt
$ stat dir1/
File: dir1/
Size: 20480 Blocks: 40 IO Block: 4096 directory
Device: 802h/2050d Inode: 398016 Links: 2
Access: (0775/drwxrwxr-x) Uid: ( 1000/ alex) Gid: ( 1000/ alex)
Access: 2022-05-16 08:43:30.267484822 +0000
Modify: 2022-05-16 08:44:19.767639652 +0000
Change: 2022-05-16 08:44:19.767639652 +0000
Birth: 2022-05-16 08:43:30.267484822 +0000
- 500 файлов в каталоге увеличило его размер до 20480 байт.
Файлы и каталоги это самые понятные типы файлов в Linux, ниже рассмотрим более необычные типы.
Файлы устройств
Устройства в Linux тоже представлены файлами, для них даже выделен каталог /dev который хранит виртуальную файловую систему devfs. Эта файловая система хранит список всех устройств компьютера. Такие устройства разделяются на символьные и блочные.
Вот пример некоторых устройств.
Виртуальное устройство консоли к которой мы подключаемся /dev/tty:
$ ls -l -i /dev/tty
12 crw-rw-rw- 1 root tty 5, 0 мая 16 08:36 /dev/tty
USB устройство подключенное к USB шине:
$ ls -l -i /dev/bus/usb/001/001
144 crw-rw-r-- 1 root root 189, 0 мая 16 08:36 /dev/bus/usb/001/001
Диски и их разделы:
$ ls -l -i /dev/sd*
220 brw-rw---- 1 root disk 8, 0 мая 16 08:36 /dev/sda
268 brw-rw---- 1 root disk 8, 1 мая 16 08:36 /dev/sda1
269 brw-rw---- 1 root disk 8, 2 мая 16 08:36 /dev/sda2
270 brw-rw---- 1 root disk 8, 3 мая 16 08:36 /dev/sda3
Как видите, все эти устройства представлены файлами. На символьные устройства указывает символ c, а на блочные символ b.
Блочные устройства это диски и их разделы, raid-массивы, и тому подобное. Эти устройства могут хранить файловую систему и файлы на ней. Они умеют обрабатывать операции ввода-вывода, то-есть умеют записывать или считывать блоки данных. И обычно поддерживают произвольный доступ к данным.
Символьные устройства это COM-порты, LPT-порты, PS/2-мышки и клавиатуры, USB-мышки и клавиатуры. Такие устройства обычно поддерживают операции (read, write, open, close). И поддерживают посимвольный, то-есть последовательный доступ к данным.
Файлы устройств это не сами устройства, например файл диска будет иметь нулевой размер, хотя сам диск может хранить много данных. Файлы устройств — это интерфейсы, позволяющие системе и программам получить доступ к устройствам. Получается что файловая система devfs расположенная в каталоге /dev это как-бы API для доступа к оборудованию.
Давайте посмотрим на символьное устройство с помощью утилиты stat:
$ stat /dev/bus/usb/001/001
File: /dev/bus/usb/001/001
Size: 0 Blocks: 0 IO Block: 4096 character special file
Device: 5h/5d Inode: 144 Links: 1 Device type: bd,0
Access: (0664/crw-rw-r--) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2022-05-16 08:36:04.872000000 +0000
Modify: 2022-05-16 08:36:04.872000000 +0000
Change: 2022-05-16 08:36:04.872000000 +0000
Birth: -
- Тип этого файла character special file — символьный специальный файл.
И посмотрим на файл блочного устройства:
$ stat /dev/sda2
File: /dev/sda2
Size: 0 Blocks: 0 IO Block: 4096 block special file
Device: 5h/5d Inode: 269 Links: 1 Device type: 8,2
Access: (0660/brw-rw----) Uid: ( 0/ root) Gid: ( 6/ disk)
Access: 2022-05-16 08:36:10.956000000 +0000
Modify: 2022-05-16 08:36:05.296000000 +0000
Change: 2022-05-16 08:36:05.296000000 +0000
Birth: -
- Тип такого файла block special file — блочный специальный файл.
Кстати, команда ls -l выводит не размер файла устройства, так как размер таких файлов всегда нулевой, а мажорный и минорный номера:
$ ls -l /dev/sda2
brw-rw---- 1 root disk 8, 2 мая 16 08:36 /dev/sda2
- мажорный номер (8) - это номер драйвера, который обслуживает это устройство;
- минорный номер (2) - это внутренний номер устройства в данной системе.
Файлы сокетов
Для взаимодействия программ друг с другом часто используются сокеты. На сокеты в выводе ls -l указывает символ s.
Следующий пример будет работать в Ubuntu 22.04, но чтобы выполнить его на Debian 11 вначале нужно установить программу netcat таким образом:
alex@deb:~$ su -
Пароль:
root@deb:~# apt install netcat
root@deb:~# exit
выход
Дело в том, что в Debian 11 по умолчанию немного другая версия netcat и в ней нет опции -U.
Создать сокет можно с помощью команды nc -lU socket.sock:
$ nc -lU socket.sock
После выполнения этой команды вы подключитесь к сокету и сможете в него что-нибудь записывать, например:
$ nc -lU socket.sock
123
333
123
Aaa...
Теперь подключитесь к серверу с помощью другого ssh соединения. И из нового окна терминала подключитесь к этому-же сокету:
$ nc -U socket.sock
123
333
123
Aaa...
Вы увидите всё то, что вводили в первом терминале.

После этого на первом терминале нажмите комбинацию клавиш Ctrl + c, чтобы закрыть сокет. Пока не будем закрывать второй терминал, он нам ещё понадобится.
Посмотрим на файл сокета с помощью утилиты stat:
alex@ubu:~$ stat socket.sock
File: socket.sock
Size: 0 Blocks: 0 IO Block: 4096 socket
Device: 802h/2050d Inode: 398517 Links: 1
Access: (0775/srwxrwxr-x) Uid: ( 1000/ alex) Gid: ( 1000/ alex)
Access: 2022-05-16 08:50:00.897716333 +0000
Modify: 2022-05-16 08:49:21.881547299 +0000
Change: 2022-05-16 08:49:21.881547299 +0000
Birth: 2022-05-16 08:49:21.881547299 +0000
- Тип файла — socket, и размер у него нулевой.
Символьные ссылки
Про ссылки будет отдельная статья, но здесь разберём этот тип файлов тоже. Символьная ссылка это файл, который указывает на другой файл.
После эксперимента с сокетом, у нас в каталоге остался файл сокета. Давайте сделаем символьную ссылку на этот файл с помощью команды ln -s <путь к файлу> <имя ссылки>:
alex@ubu:~$ ln -s socket.sock ./socket.sock.link
alex@ubu:~$ ls -l
total 20
drwxrwxr-x 2 alex alex 20480 мая 16 08:44 dir1
srwxrwxr-x 1 alex alex 0 мая 16 08:49 socket.sock
lrwxrwxrwx 1 alex alex 11 мая 16 08:51 socket.sock.link -> socket.sock
Как видите, на файл ссылки указывает символ l. Теперь можно ссылку использовать как файл, например можно подключиться к сокету используя ссылку. Вот для этого примера нам понадобится второе окно терминала, которое мы запускали раньше:

Посмотрим на символическую ссылку с помощью утилиты stat:
alex@ubu:~$ stat socket.sock.link
File: socket.sock.link -> socket.sock
Size: 11 Blocks: 0 IO Block: 4096 symbolic link
Device: 802h/2050d Inode: 398518 Links: 1
Access: (0777/lrwxrwxrwx) Uid: ( 1000/ alex) Gid: ( 1000/ alex)
Access: 2022-05-16 08:51:40.434119694 +0000
Modify: 2022-05-16 08:51:34.426096138 +0000
Change: 2022-05-16 08:51:34.426096138 +0000
Birth: 2022-05-16 08:51:34.426096138 +0000
- Тип файла — symbolic link (символьная ссылка). Размер этой ссылки 11 байт. По сути, символьные ссылки это тоже самое что и ярлыки в Windows. Можно создать ссылку на любой файл или каталог.
Итог
Вот мы и разобрали все типы файлов, которые встречаются в Linux:
- обычные файлы (
-); - каталоги (
d); - символьные устройства (
c); - блочные устройства (
b); - сокеты (
s); - символьные ссылки (
l).
Если понравилась статья, подпишись на мой канал в VK или Telegram .