Ненавидит навалить с еще одной реализацией, но мне нужен было) реализация портативных, чистые оболочки, и б) блока-тестовое покрытие, как число реберных случаев что-то вроде этого являются нетривиальный.
См. my project on Github для испытаний и полного кода. Ниже представлен краткий обзор реализации:
Как Кит Смит проницательно указывает, readlink -f
делает две вещи: 1) решает симлинки рекурсивно, и 2) канонизирует результат, следовательно:
realpath() {
canonicalize_path "$(resolve_symlinks "$1")"
}
Во-первых, символическая реализация распознаватель:
resolve_symlinks() {
local dir_context path
path=$(readlink -- "$1")
if [ $? -eq 0 ]; then
dir_context=$(dirname -- "$1")
resolve_symlinks "$(_prepend_path_if_relative "$dir_context" "$path")"
else
printf '%s\n' "$1"
fi
}
_prepend_path_if_relative() {
case "$2" in
/*) printf '%s\n' "$2" ;;
*) printf '%s\n' "$1/$2" ;;
esac
}
Обратите внимание, что это немного упрощенная версия the full implementation. Полная реализация добавляет небольшую проверку для циклов симлинк, а также немного массирует результат.
Наконец, функция для канонизации путь:
canonicalize_path() {
if [ -d "$1" ]; then
_canonicalize_dir_path "$1"
else
_canonicalize_file_path "$1"
fi
}
_canonicalize_dir_path() {
(cd "$1" 2>/dev/null && pwd -P)
}
_canonicalize_file_path() {
local dir file
dir=$(dirname -- "$1")
file=$(basename -- "$1")
(cd "$dir" 2>/dev/null && printf '%s/%s\n' "$(pwd -P)" "$file")
}
Вот это, более или менее. Достаточно просто вставить в свой скрипт, но достаточно сложно, чтобы вы были сумасшедшими, чтобы полагаться на любой код, который не имеет модульных тестов для ваших случаев использования.
Немного поздно, но в вашем вопросе отсутствует упоминание оболочки, которую вы используете. Это актуально, поскольку 'readlink' может быть встроенной или внешней командой. – 0xC0000022L
Это могло бы объяснить разницу. Я уверен, что я использовал bash в обоих случаях. – troelskn
Почему эта опция незаконна на компьютерах Mac? – CommaToast