这是对@pini目前评价最高的解决方案的一个经过纠正的全功能改进(遗憾地只处理了几个案例)
提醒:“-z”测试如果字符串是零长度(=空)和“-n”测试如果字符串是不空的。
# both $1 and $2 are absolute paths beginning with /
# returns relative path to $2/$target from $1/$source
source=$1
target=$2
common_part=$source # for now
result=”” # for now
while [[ “${target#$common_part}” == “${target}” ]]; do
# no match, means that candidate common part is not correct
# go up one level (reduce common part)
common_part=”$(dirname $common_part)”
# and record that we went back, with correct / handling
if [[ -z $result ]]; then
result=”..”
else
result=”../$result”
fi
done
if [[ $common_part == “/” ]]; then
# special case for root (no common path)
result=”$result/”
fi
# since we now have identified the common part,
# compute the non-common part
forward_part=”${target#$common_part}”
# and now stick all parts together
if [[ -n $result ]] && [[ -n $forward_part ]]; then
result=”$result$forward_part”
elif [[ -n $forward_part ]]; then
# extra slash removal
result=”${forward_part:1}”
fi
echo $result
测试用例 :
compute_relative.sh “/A/B/C” “/A” –> “../..”
compute_relative.sh “/A/B/C” “/A/B” –> “..”
compute_relative.sh “/A/B/C” “/A/B/C” –> “”
compute_relative.sh “/A/B/C” “/A/B/C/D” –> “D”
compute_relative.sh “/A/B/C” “/A/B/C/D/E” –> “D/E”
compute_relative.sh “/A/B/C” “/A/B/D” –> “../D”
compute_relative.sh “/A/B/C” “/A/B/D/E” –> “../D/E”
compute_relative.sh “/A/B/C” “/A/D” –> “../../D”
compute_relative.sh “/A/B/C” “/A/D/E” –> “../../D/E”
compute_relative.sh “/A/B/C” “/D/E/F” –> “../../../D/E/F”