推荐采用realpath或readlink -f来获取绝对路径。其中,realpath更为可靠,它能够自动处理符号链接和路径规范化,并且在路径不存在时默认报错。而readlink -f则对老系统更为兼容,但对坏链接更为敏感。需要注意的是,pwd -P和$PWD仅适用于当前目录,无法用于任意文件。

直接用 realpath 或 readlink -f,99% 的场景下就能拿到你要的绝对路径;别用 pwd 拼接,也别手动加 / 前缀——那不是“查看”,是猜。
realpath 命令:最推荐的默认选择
realpath 是 GNU coreutils 的一部分,现代发行版基本都自带。它自动处理 .、..、重复斜杠和符号链接,输出干净、规范的绝对路径。
- 路径不存在时会报错(比如
realpath /no/such/file),这是设计行为,不是 bug;若需容忍不存在路径,加--no-symlinks仅做字符串规范化 - 支持批量:
realpath ./a ../b/c /tmp/../var/log一次输出三行结果 - 对符号链接默认穿透,但不会因中间某级链接损坏而失败——只要最终路径可访问,就返回结果;如果链接链里有坏链,
realpath可能仍成功(取决于 shell 解析逻辑),而readlink -f通常直接退出非零状态
readlink -f:老系统兼容性更强的选择
readlink -f 更底层,不依赖 GNU 扩展,在 CentOS 6、某些嵌入式或最小化系统里更可能预装。但它对路径存在性更敏感。
- 目标路径中任意一级符号链接指向不存在的位置,
readlink -f就会失败,返回空或报错 - 不接受不存在的路径作为输入:
readlink -f /tmp/missing不输出任何内容,且退出码为 1 - 不支持
--no-symlinks这类选项,想绕过链接解析就得换方法(比如先ls -l看是不是链接) - 在脚本里用时建议加判断:
if ! abs_path=$(readlink -f "$file" 2>/dev/null); then echo "invalid path"; exit 1; fi
pwd -P 和 $PWD:只适合当前目录,别乱套用
pwd -P能够返回当前工作目录的物理路径,也就是将所有符号链接解开后的实际位置。而$PWD是shell所记录的逻辑路径。需要注意的是,这两者都仅仅作用于当前目录,无法直接用于任意文件。
- 想查当前目录的绝对路径?直接
pwd -P,比realpath .少一次 fork,更快 - 想拼接子文件路径?用
"$PWD/file.txt"比"$(pwd)/file.txt"安全高效,但必须加双引号,否则含空格路径会崩 $PWD在 chroot、容器或某些异常 shell 启动场景下可能未初始化,这时pwd -P是唯一可靠 fallback- 千万别写
cd /some/path && pwd来“获取”路径——这会改变当前目录,破坏脚本上下文
哪些方法容易踩坑
别碰这些看似简单实则危险的操作:
- 手动拼接:
"/home/user/" + "sub/dir"—— 缺少路径分隔符校验,sub开头是/就直接覆盖根路径 - 用
which查普通文件:which myfile.sh只查$PATH里的可执行文件,跟路径无关 - 误信
find . -name xxx | head -1—— 输出的是相对路径,不是绝对路径;要绝对路径得写find "$PWD" -name xxx,但性能差、易漏权限错误 - 用
stat -c "%n" file—— 它输出的是传入参数的原始字符串,不是解析后的绝对路径;stat -c "%n" ./a还是输出./a
真正容易被忽略的是:路径是否“存在”和是否“可解析”是两回事;realpath 和 readlink -f 的行为差异,往往只在符号链接链断裂或跨挂载点时才暴露出来——等线上脚本出问题再查,代价远大于提前验证一次。