С чего начать Первые шаги трек · 15 ступеней
Linux Labs

Пути — basename, dirname, realpath

3 мин GNU coreutils

Разобрать путь на имя и каталог, получить абсолютный путь; устойчивый каталог скрипта.

Шпаргалка

5 команд Версия для печати
  • basename /a/b/c.txt c.txt
  • basename /a/b/c.txt .txt c
  • dirname /a/b/c.txt /a/b
  • realpath ../x абсолютный путь
  • SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" каталог скрипта

Обзор

Утилиты для работы с путями как со строками — незаменимы в скриптах:

  • basename — имя файла без каталога (и, опц., без расширения).
  • dirname — каталог без имени файла.
  • realpath — абсолютный путь после раскрытия ., .. и симлинков.
bash
basename /var/log/syslog          # syslog
basename /var/log/app.log .log    # app           (убрать суффикс)
dirname  /var/log/syslog          # /var/log
realpath ../../etc/nginx          # /etc/nginx    (абсолютный, без ../)
realpath -m /nope/x               # посчитать путь, даже если его нет (-m)

Ключи

6

У каждой из трёх утилит свой небольшой набор ключей. basename -s убирает суффикс без отдельного вызова sed, -a берёт сразу несколько путей. realpath -e требует, чтобы весь путь реально существовал, а -m наоборот — считает путь строкой, даже если файла ещё нет; путать их — частая причина ошибок в скриптах, которые готовят путь для файла, который сами же создадут.

Ключ Что делает Пример
-m --canonicalize-missing realpath: посчитать путь, даже если он или его часть не существует. realpath -m /nope/x
-s --suffix SUFFIX basename: убрать указанный суффикс из имени. basename -s .txt /a/b/c.txt
-e --canonicalize-existing realpath: требовать, чтобы весь путь существовал; иначе — ошибка. realpath -e /etc/hosts
-s --strip realpath: не разворачивать символические ссылки, только . и ... realpath -s ../x
-a --multiple basename: несколько имён сразу, каждое своей строкой. basename -a /a/x /b/y
-z --zero Разделять вывод нулевым байтом вместо перевода строки. basename -z /a/b/c.txt

Ничего не найдено. Попробуй запрос короче.

Рецепты

1

В скриптах

Классика — узнать каталог самого скрипта, чтобы пути не зависели от того, откуда его запустили:

bash
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"     # переносимо
# или короче через realpath:
SCRIPT_DIR="$(dirname "$(realpath "$0")")"

Разобрать путь на части:

bash
path=/srv/www/site/index.html
dir=$(dirname  "$path")           # /srv/www/site
base=$(basename "$path")          # index.html
name=$(basename "$path" .html)    # index

В чистом bash то же дают подстановки: ${path##*/} (basename) и ${path%/*} (dirname) — без вызова внешней программы. См. bash-scripting.

Неполадки

3

Путь с пробелами «разъехался»

Всегда в кавычках: dirname "$path". Без кавычек пробел разобьёт аргументы.

realpath: No such file or directory

По умолчанию realpath требует существования пути. Для несуществующих — -m (посчитать чисто строкой) или -e (наоборот, требовать существования всех частей).

Нужен путь без раскрытия симлинков

realpath идёт по симлинкам. Чтобы оставить как есть — realpath -s (или readlink для самой ссылки, см. ln).

Термины

2
абсолютный путь absolute path
Путь, который начинается с / и указывает на файл от корня файловой системы; результат не зависит от текущего каталога. Пример: /etc/ssh/sshd_config. Ещё встречается в: at, Cron, ln
относительный путь relative path
Путь без начального /, который отсчитывается от текущего каталога процесса. Компоненты . и .. обозначают сам каталог и родительский. Ещё встречается в: Таймеры systemd, ln, ls, tar

См. также

  • files-basics — Навигация и файлы — ls, cd, cp, mv, rm, cat, less, head, tail, копипаст в терминале.
  • cd — Перемещение по файловой системе: cd, cd -, cd ~, cd .., pushd/popd, CDPATH.
  • bash-scripting — Переменные, условия, циклы, аргументы и безопасный режим set -euo pipefail.
Загрузка…