Linux shell中如何基于参考目录获取文件的相对路径?
POSIX 兼容的相对路径计算函数实现
原有实现的问题
你当前的实现依赖realpath工具,该工具并未纳入POSIX标准规范,在部分精简环境(如默认配置的busybox、嵌入式shell环境、最小化发行版)中可能不存在,兼容性不足。
兼容实现方案
以下实现仅使用POSIX标准规定的工具与语法,可在所有符合POSIX规范的shell环境中运行:
# 功能:计算从目标文件所在目录到基准目录的相对路径 # 参数1:目标文件路径 # 参数2:基准目录路径 get_relative_path() { # 内部工具函数:将任意路径转为标准化绝对路径,消除./ ../与多余斜杠 _to_abs_path() { local path p part path="$1" # 相对路径拼接当前工作目录转为绝对路径 if [ "${path#/}" = "$path" ]; then path="$(pwd)/$path" fi p="" IFS='/' for part in $path; do unset IFS case "$part" in ''|'.') continue ;; '..') p="${p%/*}" ;; *) p="$p/$part" ;; esac done echo "${p:-/}" } local file abs_file file_dir abs_main rel_path file="$1" abs_file="$(_to_abs_path "$file")" # 提取目标文件所在的目录 file_dir="${abs_file%/*}" abs_main="$(_to_abs_path "$2")" rel_path="" # 逐段向上匹配公共目录前缀 while [ "$file_dir" != "$abs_main" ] && [ "$file_dir" != "/" ]; do rel_path="../$rel_path" file_dir="${file_dir%/*}" done # 去掉末尾多余斜杠,同级目录返回空字符串方便直接拼接资源名 rel_path="${rel_path%/}" echo "$rel_path" }
测试验证
对应你给出的场景测试结果如下:
# 测试1:文件在docs目录下,基准目录为项目根目录 f="docs/readme.html" main_dir="./" path="$(get_relative_path "$f" "$main_dir")" echo "${path}styles.css" # 输出 ../styles.css,可直接用于HTML引用 # 测试2:文件在docs/2021目录下,基准目录为项目根目录 f="docs/2021/readme.html" main_dir="./" path="$(get_relative_path "$f" "$main_dir")" echo "${path}styles.css" # 输出 ../../styles.css # 测试3:文件在项目根目录,基准目录为项目根目录 f="index.html" main_dir="./" path="$(get_relative_path "$f" "$main_dir")" echo "${path}styles.css" # 输出 styles.css,符合需求
优化说明
- 内置路径标准化逻辑完全基于POSIX字符串操作实现,不依赖任何非标准外部工具,兼容性更强
- 无多余管道调用,执行效率比原有多管道方案更高
- 自动处理路径中的多余斜杠、相对路径标记,容错性更好
- 输出结果可直接拼接资源文件名,无需额外处理斜杠
内容的提问来源于stack exchange,提问作者luarpy
相关产品推荐
相关产品推荐

