Yine başka bir uygulama ile uğraşmaktan nefret ediyorum, ancak a) taşınabilir, saf bir kabuk uygulamasına ve b) birim test kapsamına ihtiyacım vardı , çünkü böyle bir şey için uç vakaların sayısı önemsiz değildir .
Testler ve tam kod için Github'daki projeme bakın . Aşağıdakiler uygulamanın bir özetidir:
Keith Smith'in açıkça belirttiği gibi readlink -f
, iki şey yapar: 1) sembolik bağlantıları yinelemeli olarak çözer ve 2) sonucu kanonikleştirir, dolayısıyla:
realpath() {
canonicalize_path "$(resolve_symlinks "$1")"
}
İlk olarak, symlink çözümleyici uygulaması:
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
}
Bunun tam uygulamanın biraz basitleştirilmiş bir sürümü olduğunu unutmayın . Tam uygulama, sembolik bağlantı döngüleri için küçük bir kontrol ekler , ayrıca çıktıya biraz masaj yapar.
Son olarak, bir yolu standartlaştırma işlevi:
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")
}
Aşağı yukarı bu kadar. Betiğinize yapıştıracak kadar basit, ancak kullanım durumlarınız için birim testleri olmayan herhangi bir koda güvenmek için çılgın olacağınız kadar zor.
readlink
bir yerleşik veya harici komut olabilir.