Как получить полный PATH, * разрешающий * для символических ссылок - PullRequest
0 голосов
/ 19 февраля 2019

Я написал сценарии bash, которые принимают имя каталога в качестве аргумента.Одна точка ('.') Является допустимым именем каталога, но мне иногда нужно знать, где '.'является.Команды readlink и realpath предоставляют разрешенный путь, что не помогает, поскольку мне нужно разрешить символические ссылки.

Например, разрешенный путь к указанному каталогу может быть примерно таким: /mnt/vol_01/and/then/someтогда как скрипт вызывается с помощью «.»где '.'is /app/then/some (символьная ссылка, которая разрешает первый указанный мной путь).

Что я сделал, чтобы решить мою проблему, так это использование cd и pwd в комбинации для обеспечения полного пути Iхочу, и, кажется, до сих пор работало нормально.

Упрощенный пример сценария:

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 Ответ

0 голосов
/ 19 февраля 2019

Если все, что вы хотите сделать, это сделать абсолютный путь, который имеет минимальные изменения относительно относительного пути, то простой, безопасный и быстрый путь к нему:

[[ $dest_dir == /* ]] || dest_dir=$PWD/$dest_dir

(см. Исправьте заглавные буквы переменной Bash и сценария оболочки для объяснения того, почему 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 '.'
...