readlink 不加参数只输出软链接原始目标路径(含相对路径),加 -f 递归解析并返回绝对路径,-e 要求最终目标必须存在才输出。

直接用 readlink 就能拿到软连接指向的路径,但不加参数只返回相对路径,加 -f 才能得到绝对路径——这是最常被忽略的关键点。
不加参数时只输出原始目标路径(可能含 ../ 或相对路径)
比如软连接 mylink 指向 ../data/config.yaml,执行 readlink mylink 就原样输出 ../data/config.yaml,不会自动补全或解析。
- 适用于你只想确认链接“写的是什么”,不关心它最终落在哪
- 如果目标本身又是软连接,
readlink不会递归展开,只读第一层 - 返回值为空(即命令无输出)说明该路径不是软连接,或权限不足
readlink -f 递归解析并返回绝对路径
-f 是实际使用中最常用的选项:它会一路跟下去,直到遇到真实文件或目录,并把整个路径转成绝对形式。
- 要求路径中所有中间组件(包括父目录、每一级软链)都必须存在,否则报错退出
- 若软链链成环(A→B→A),
readlink -f会报错:readlink: error: too many levels of symbolic links - 即使目标文件已被删除,只要路径结构还在,
-f仍会返回“理论上”的绝对路径(这点和realpath行为一致)
readlink -e 更严格的递归解析
和 -f 类似,但多一层校验:要求最终目标**必须存在**,否则返回空。
- 适合脚本中做安全判断,比如部署前验证配置软链是否真正指向有效文件
- 当软链末尾指向一个已删掉的文件时,
readlink -e不输出任何内容,而readlink -f仍会输出路径 - 注意:
-e在较老的 GNU coreutils 版本(如 CentOS 6 默认)中不可用,需确认系统支持
脚本里用 readlink 安全取路径的常见坑
直接写 $(readlink -f path) 看似简单,但在路径含空格、换行或特殊字符时容易出问题。
- 务必用双引号包裹结果:
target="$(readlink -f "$path")",否则空格会导致变量截断 - 如果
$path可能为空或不存在,readlink -f会报错并让脚本中断,建议加判断:[[ -L "$path" ]] && target=$(readlink -f "$path") -
readlink返回值是字符串长度,成功时非负,失败时为 0 或负值;但 shell 脚本里更可靠的方式是检查命令退出码,而非返回值
真正麻烦的不是怎么写命令,而是软链嵌套层数、路径是否存在、以及目标是否跨挂载点——这些情况 readlink -f 都不报错,但结果可能不符合预期。动手前先用 ls -l 看一眼链式结构,比硬试更省时间。


















