मुझे अभी तक एक और कार्यान्वयन के साथ ढेर करने से नफरत है, लेकिन मुझे एक) पोर्टेबल, शुद्ध शेल कार्यान्वयन , और बी) यूनिट-टेस्ट कवरेज की आवश्यकता थी , क्योंकि इस तरह के कुछ के लिए किनारे-मामलों की संख्या गैर-तुच्छ है ।
परीक्षण और पूर्ण कोड के लिए 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
}
ध्यान दें कि यह पूर्ण कार्यान्वयन का थोड़ा सरलीकृत संस्करण है । पूर्ण क्रियान्वयन से सिमलिंक चक्रों के लिए एक छोटा सा चेक जोड़ा जाता है , साथ ही साथ आउटपुट को थोड़ा मालिश करता है।
अंत में, एक मार्ग को स्पष्ट करने के लिए कार्य:
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
एक अंतर्निहित या बाहरी कमांड हो सकता है।