Как получить полный PATH, * разрешающий * для символических ссылок
Я написал сценарии bash, которые принимают имя каталога в качестве аргумента. Одна точка ('.') Является допустимым именем каталога, но мне иногда нужно знать, где '.' является. readlink
а также realpath
Команды предоставляют разрешенный путь, который не помогает, потому что мне нужно разрешить символические ссылки.
Например, разрешенный путь к данному каталогу может быть что-то вроде /mnt/vol_01/and/then/some
тогда как скрипт вызывается с помощью "." где '.' является /app/then/some
(Сим-ссылка, которая будет разрешена на первый путь, который я дал).
Что я сделал, чтобы решить мою проблему, это использовать cd
а также pwd
в сочетании, чтобы обеспечить полный путь, который я хочу, и, кажется, до сих пор работал нормально.
Упрощенный пример скрипта:
DEST_DIR=$1
# Convert the given destination directory to a full path, ALLOWING
# for symbolic links. This is necessary in cases where '.' is
# given as the destination directory.
DEST_DIR=$(cd $DEST_DIR && pwd -L)
# Do stuff in $DEST_DIR
Мой вопрос: мое использование cd
а также pwd
лучший способ получить то, что я хочу? Или есть лучший способ?
1 ответ
Если все, что вы хотите сделать, это создать абсолютный путь, который имеет минимальные изменения относительно относительного пути, то простой, безопасный и быстрый путь к нему:
[[ $dest_dir == /* ]] || dest_dir=$PWD/$dest_dir
(См. Правильное использование заглавных букв в сценариях Bash и shell для объяснения причин dest_dir
предпочтительнее DEST_DIR
.)
Приведенный выше код будет работать, даже если каталог не существует (пока) или если невозможно cd
к нему (например, потому что его разрешения не позволяют это). Может создавать пути с избыточным '.' компоненты, компоненты.. и избыточные слэши (`/a//b', '//a/b/', ...).
Если вы хотите минимально очищенный путь (оставив символьные ссылки нерешенными), тогда разумной возможностью может стать измененная версия исходного кода:
dest_dir=$(cd -- "$dest_dir"/ && pwd)
--
необходимо обрабатывать имена каталогов, которые начинаются с '-'.- Цитаты в
"$dest_dir"
необходимы для обработки имен, которые содержат пробелы (на самом деле$IFS
символы) или глобус символов. - Конечный слеш на
"$dest_dir"/
необходимо обрабатывать каталог, относительное имя которого просто-
, - гладкий
pwd
достаточно, потому что он ведет себя так, как будто-L
был указан по умолчанию.
Обратите внимание, что код будет установлен dest_dir
в пустую строку, если cd
выходит из строя. Вы, вероятно, хотите проверить это, прежде чем делать что-то еще с переменной.
Обратите внимание, что $(cd ...)
создаст подоболочку с Bash. Это хорошо с одной стороны, потому что нет необходимости cd
впоследствии вернитесь в начальный каталог (что может быть невозможно), но это может вызвать проблемы с производительностью, если вы делаете это много (например, в цикле).
Наконец, обратите внимание, что код не будет работать, если имя каталога содержит одну или несколько завершающих строк новой строки (например, созданных mkdir $'dir\n'
). Можно решить проблему (если вы действительно заботитесь об этом), но это грязно. См. Как избежать подстановки команд bash для удаления символа новой строки? и shell: оставляйте завершающие символы новой строки ('\n') в подстановке команд. Один из возможных способов сделать это:
dest_dir=$(cd -- "$dest_dir"/ && printf '%s.' "$PWD") # Add a trailing '.'
dest_dir=${dest_dir%.} # Remove the trailing '.'