Наверное, лучше поздно, чем никогда. Я был мотивирован, чтобы разработать это специально, потому что мои скрипты Fedora не работали на Mac. Проблема в зависимостях и Bash. У Mac их нет, или, если они есть, они часто находятся где-то еще (другой путь). Манипулирование путями зависимости в кроссплатформенном скрипте Bash в лучшем случае является головной болью, а в худшем - угрозой безопасности, поэтому лучше по возможности избегать их использования.
Функция get_realpath () ниже проста, ориентирована на Bash, и никаких зависимостей не требуется. Я использую только встроенные в Bash echo и cd . Это также довольно безопасно, так как все проверяется на каждом этапе пути и возвращает ошибки.
Если вы не хотите переходить по символическим ссылкам, поместите set -P в начало сценария, но в противном случае cd должен разрешить символические ссылки по умолчанию. Это было проверено с аргументами файла, которые являются {absolute | родственник | символическая ссылка | local} и возвращает абсолютный путь к файлу. До сих пор у нас не было никаких проблем с этим.
function get_realpath() {
if [[ -f "$1" ]]
then
# file *must* exist
if cd "$(echo "${1%/*}")" &>/dev/null
then
# file *may* not be local
# exception is ./file.ext
# try 'cd .; cd -;' *works!*
local tmppwd="$PWD"
cd - &>/dev/null
else
# file *must* be local
local tmppwd="$PWD"
fi
else
# file *cannot* exist
return 1 # failure
fi
# reassemble realpath
echo "$tmppwd"/"${1##*/}"
return 0 # success
}
Вы можете комбинировать это с другими функциями get_dirname, get_filename, get_stemname и validate_path. Их можно найти в нашем репозитории GitHub как realpath-lib (полное раскрытие информации - это наш продукт, но мы предлагаем его бесплатно для сообщества без каких-либо ограничений). Он также может служить инструктивным инструментом - он хорошо документирован.
Мы старались изо всех сил применять так называемые практики «современного Bash», но Bash - это важная тема, и я уверен, что всегда найдется место для улучшения. Требуется Bash 4+, но его можно настроить для работы со старыми версиями, если они все еще существуют.
readlink
может быть встроенной или внешней командой.