← Весь справочник

basename, dirname, realpath, readlink

Разбор путей — имя файла, каталог, абсолютный путь, куда ведёт ссылка

Четыре маленькие утилиты для работы с путями. basename и dirname режут строку пути и не обращаются к диску. realpath и readlink смотрят в файловую систему: раскрывают символические ссылки, . и ... В довесок — namei, который показывает каждый шаг пути с правами. В песочнице — GNU coreutils 9.4 и util-linux.

Синтаксис

basename путь [суффикс]
basename -a [-s суффикс] путь…
dirname путь…
realpath [опции] путь…
readlink [опции] ссылка…
namei [опции] путь…

basename — последняя часть пути

ВызовРезультат
basename /var/log/nginx/access.logaccess.log
basename /var/log/nginx/access.log .logaccess — суффикс отрезан
basename /var/log/log — косая черта в конце игнорируется
basename //
basename .log .log.log — суффикс не отрезается, если он равен всему имени
ОпцияЧто делает
-s суффиксотрезать суффикс; подразумевает -a
-aпринять несколько путей, по результату на строку
-zразделять результаты нулевым байтом

dirname — всё, кроме последней части

ВызовРезультат
dirname /var/log/nginx/access.log/var/log/nginx
dirname file.txt. — текущий каталог
dirname /var/log//var
dirname //
dirname a/b c/da и c — по строке на путь

realpath — канонический абсолютный путь

Раскрывает все ссылки, ., .. и лишние /. По умолчанию все компоненты, кроме последнего, должны существовать.

ОпцияЧто делает
(без опций)физический путь: ссылки раскрыты, последний компонент может не существовать
-eвсе компоненты обязаны существовать, иначе ошибка
-mничего не обязано существовать — чисто строковая нормализация
-sне раскрывать ссылки, только убрать ., .., //
-Lсначала обработать .., потом ссылки (как cd/pwd в bash)
-Pсначала ссылки, потом .. (по умолчанию)
--relative-to=каталогвывести путь относительно каталога
--relative-base=каталоготносительный путь, только если цель внутри каталога; иначе абсолютный
-qне печатать ошибки
-zразделять результаты нулевым байтом

readlink — содержимое символической ссылки

ОпцияЧто делает
(без опций)путь, записанный в ссылке, как есть (может быть относительным). Не ссылка — пусто и код 1
-fканонический путь: раскрыть все ссылки рекурсивно; последний компонент может не существовать
-eкак -f, но всё должно существовать
-mкак -f, но ничего не обязано существовать
-nне печатать перевод строки в конце
-vсообщать об ошибках (по умолчанию readlink молчит)

readlink -f и realpath почти одинаковы; realpath нагляднее и умеет относительные пути.

namei — разбор пути по шагам

Показывает каждый компонент пути, его тип и куда ведут ссылки. Главное применение — понять, на каком каталоге пути не хватает прав.

ОпцияЧто делает
-lдлинный формат: права + владелец + группа (-m -o -v)
-mправа каждого компонента
-oвладелец и группа
-xточки монтирования помечать D вместо d
-nне раскрывать символические ссылки
$ namei -l /etc/os-release
f: /etc/os-release
drwxr-xr-x root root /
drwxr-xr-x root root etc
lrwxrwxrwx root root os-release -> ../usr/lib/os-release
drwxr-xr-x root root   ..
drwxr-xr-x root root   usr
drwxr-xr-x root root   lib
-rw-r--r-- root root   os-release

Примеры

# имя файла без расширения
basename /data/report.csv .csv

# отрезать суффикс у нескольких путей
basename -s .log /var/log/app.log /var/log/db.log

# каталог, где лежит сам скрипт (работает при вызове из любого места)
script_dir=$(dirname "$(realpath "$0")")

# куда указывает ссылка: как записано и итоговый путь
readlink /srv/app/current
readlink -f /srv/app/current

# путь из одного каталога в другой — для ln -s
realpath --relative-to=/etc /var/log

# нормализовать путь, которого ещё нет
realpath -m /srv/app/../data//new

# почему пользователь не может прочитать файл: права на каждом шаге
namei -l /srv/app/config/secret.yml

# то же без внешних команд — средствами bash
f=/srv/app/data.tar.gz
echo "${f##*/}"   # data.tar.gz — как basename
echo "${f%/*}"    # /srv/app — как dirname

Подводные камни

  • basename/dirname не знают о файловой системе. dirname ссылка вернёт каталог ссылки, а не цели. Для реального места — realpath.
  • readlink без -f возвращает путь как записан — часто относительный (../current/x) и считается от каталога ссылки, а не от текущего.
  • readlink на обычном файле молча печатает пусто и возвращает 1. С -v видно причину: «Invalid argument».
  • realpath и несуществующие каталоги. realpath /no/such — ошибка, потому что нет /no. Если нужна только нормализация строки — -m.
  • .. и ссылки. Если current — ссылка на releases/v2, то realpath current/.. даст /srv/app/releases (физически), а realpath -L current/.. и cd current/.. — /srv/app.
  • Суффикс у basename — это строка, а не шаблон: basename a.tar.gz .gz → a.tar, а '*.gz' ничего не отрежет.
  • Пробелы. Всегда бери в кавычки и аргумент, и подстановку: dirname "$(realpath "$0")".

См. также

ln · ls · stat · chmod · variables · find