菜鸟科技网

readlink命令,解析符号链接指向的真实路径?

readlink 是一个在 Linux 和 Unix-like 系统中非常实用的命令行工具,它的核心功能是“解析符号链接”,它会告诉你一个符号链接(软链接)真正指向的文件或目录的完整路径。

readlink命令,解析符号链接指向的真实路径?-图1
(图片来源网络,侵删)

什么是符号链接?

在理解 readlink 之前,必须先明白什么是符号链接。

  • 硬链接:指向文件 inode 的另一个名称,它和原始文件是同一个文件,只是有不同的名字,你不能为目录创建硬链接,也不能跨文件系统创建硬链接。
  • 符号链接:也称为“软链接”,它就像一个快捷方式或一个指针,包含一个指向另一个文件或目录的路径字符串,符号链接可以指向不存在的文件(断开的链接),也可以跨文件系统创建。

示例:

# 创建一个普通文件
$ echo "hello world" > my_file.txt
# 创建一个指向 my_file.txt 的符号链接
$ ln -s my_file.txt my_link
# my_link 就是一个符号链接

readlink 命令的基本用法

readlink 命令最基本的功能就是显示符号链接指向的目标。

基本语法

readlink [选项] <符号链接文件>

示例

# 创建一个符号链接
$ ln -s /var/log/syslog my_syslog_link
# 使用 readlink 查看它指向哪里
$ readlink my_syslog_link
/var/log/syslog

常用选项

readlink 的强大之处在于它的选项,可以处理更复杂的情况。

readlink命令,解析符号链接指向的真实路径?-图2
(图片来源网络,侵删)

-f--canonicalize

这是 最常用、也最强大 的一个选项,它会递归地解析所有符号链接,并返回最终的、规范化的绝对路径

  • 规范化:意味着它会解析路径中的 (当前目录)、 (上级目录) 以及多余的 。
  • 递归解析:如果目标本身也是一个符号链接,-f 会继续追踪下去,直到找到一个非链接的文件为止。

示例场景: 假设我们有以下文件结构和链接:

$ mkdir -p /home/user/project/src
$ touch /home/user/project/src/main.c
$ ln -s /home/user/project/src /home/user/project/code_link

我们想找到 code_link 下的 main.c 的绝对路径。

# 1. 不使用 -f,只能看到第一层指向
$ readlink code_link
/home/user/project/src
# 2. 使用 -f,可以得到最终的、规范的绝对路径
$ readlink -f code_link/main.c
/home/user/project/src/main.c

这个 -f 选项在编写脚本时极其有用,因为它总能给你一个确定无误的、完整的路径。

readlink命令,解析符号链接指向的真实路径?-图3
(图片来源网络,侵删)

-e--canonicalize-existing

-f 类似,但它会确保路径最终指向一个真实存在的文件,如果路径断开(即链接指向一个不存在的文件),它会返回错误。

# 创建一个断开的链接
$ ln -s /nonexistent/file broken_link
# -f 会返回它“应该”指向的路径,即使文件不存在
$ readlink -f broken_link
/nonexistent/file
# -e 会失败,因为文件不存在
$ readlink -e broken_link
readlink: broken_link: No such file or directory

-m--canonicalize-missing

-f 类似,但它允许路径中的任意部分不存在,它会将路径中存在的部分规范化,然后拼接上不存在的部分。

# 假设 /path/to 不存在,但 /path 存在
$ mkdir /path
$ ln -s /path/to/my_link my_link
# -f 会失败,因为 /path/to 不存在
$ readlink -f my_link
/path/to/my_link  # (如果系统允许,可能返回这个,但行为可能因实现而异)
# -m 会成功,因为它不关心中间路径是否存在
$ readlink -m my_link
/path/to/my_link

-n--no-newline

默认情况下,readlink 的输出末尾会带一个换行符,此选项会去掉末尾的换行符,这在脚本中非常有用,当你想把 readlink 的结果赋值给一个变量时,可以避免变量末尾多出一个空行。

$ target=$(readlink -n my_link)
echo "The target is: '${target}'"
# 输出: The target is: '/var/log/syslog'
# (没有多余的空行)

-s--silent

如果给定的文件不是符号链接,readlink 默认会报错并退出,使用 -s 选项可以静默处理,在这种情况下不输出任何内容并成功退出。

$ readlink not_a_link
readlink: 'not_a_link': Not a symbolic link
$ readlink -s not_a_link
# (没有任何输出,命令成功执行)

-v--verbose

显示详细的处理过程。

$ readlink -v code_link
code_link -> /home/user/project/src

在 Shell 脚本中的应用

readlink 在脚本中主要用于获取一个可靠的、绝对的路径,这对于编写健壮的脚本至关重要。

场景: 你的脚本在 /home/user/project/bin 目录下,需要操作同一项目下的 config/app.conf 文件,你希望无论从哪里运行这个脚本,它都能正确找到配置文件。

#!/bin/bash
# 获取脚本所在的目录
SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
# 使用 readlink -f 获取配置文件的绝对路径
CONFIG_FILE=$(readlink -f "${SCRIPT_DIR}/../config/app.conf")
if [ -f "$CONFIG_FILE" ]; then
    echo "Using configuration file at: $CONFIG_FILE"
    # 在这里使用 $CONFIG_FILE...
else
    echo "Error: Configuration file not found at $CONFIG_FILE" >&2
    exit 1
fi

在这个例子中,readlink -f 确保了即使 config 目录或 app.conf 是一个符号链接,我们也能得到最终的、正确的路径。


相关命令:realpath

readlink -f 的功能与 realpath 命令几乎完全相同。realpath 是一个独立的命令,旨在提供 POSIX 标准化的路径解析功能。

在大多数现代 Linux 发行版(如 Ubuntu, Debian, CentOS 7+)中,realpathcoreutils 包的一部分,非常常见。

# readlink -f 和 realpath 的效果通常是一样的
$ readlink -f my_link
/var/log/syslog
$ realpath my_link
/var/log/syslog

realpath 可用,使用它通常更具可读性,因为它明确表达了“获取真实路径”的意图,如果环境不确定,readlink -f 是一个更通用的选择,因为它在更多基础系统中是内置的 readlink 的一部分。


总结表格

选项 全称 描述
-f --canonicalize 递归解析链接,返回规范的绝对路径
-e --canonicalize-existing 类似 -f,但要求最终路径必须存在,否则报错。
-m --canonicalize-missing 类似 -f,但允许路径中的任意部分不存在
-n --no-newline 输出不包含末尾的换行符,适合用于脚本赋值。
-s --silent 如果文件不是符号链接,不报错,静默退出。
-v --verbose 显示链接指向的详细信息(如 link -> target)。
-z --zero NUL (\0) 字符分隔输出,而不是换行符,便于 xargs -0 处理。

核心要点:

  • readlink 是查看符号链接指向谁的基本命令。
  • readlink -f 是获取绝对路径的“利器”,在脚本中极为常用。
  • 它与 realpath 命令功能高度重合,realpath 有时更具可读性。
分享:
扫描分享到社交APP
上一篇
下一篇