硬链接的本质是同一文件系统中两个路径指向相同的inode和设备号。判断需用stat()获取st_ino与st_dev并同时比对,仅比较inode编号会导致跨文件系统误判;符号链接需用lstat()区分目标与链接自身;std::filesystem无法直接提取inode信息,必须依赖底层POSIX调用。

硬链接的本质是 inode 相同
在类 Unix 系统(Linux、macOS)上,两个路径互为硬链接,当且仅当它们指向同一个 inode,且位于同一文件系统。C++ 本身不提供“判断硬链接”的直接 API,必须通过系统调用获取文件元数据并比对 st_ino 和 st_dev。
用 stat() 获取并比较 inode 与设备号
关键不是只看 st_ino,因为不同文件系统可能有相同 inode 编号。必须同时确认 st_dev(设备 ID)一致,否则即使 st_ino 相同也非硬链接。
示例逻辑:
#include <sys/stat.h>
#include <unistd.h>
<p>bool are_hardlinks(const char<em> path1, const char</em> path2) {
struct stat st1, st2;
if (stat(path1, &st1) != 0 || stat(path2, &st2) != 0) return false;
return (st1.st_ino == st2.st_ino) && (st1.st_dev == st2.st_dev);
}</p>-
stat()不跟随符号链接,适合判断硬链接;若需处理符号链接本身(而非其目标),改用lstat() - Windows 不支持硬链接(NTFS 的硬链接极少被用户级程序使用,且 WinAPI 行为不同),该方法仅适用于 POSIX 环境
- 注意:
path1和path2必须是绝对路径或确保相对路径解析上下文一致,否则可能因 cwd 变化导致误判
常见误判场景和坑
容易把软链接、相同内容的文件、甚至同一文件的多个打开句柄当成硬链接——这些都不满足 st_ino == st_ino && st_dev == st_dev 条件。
立即学习“C++免费学习笔记(深入)”;
- 两个路径指向同一文件内容但分别创建(如
cp),st_ino不同 → 不是硬链接 - 一个路径是符号链接,另一个是目标文件:
stat()后者得目标 inode,前者得链接自身 inode(lstat()才得链接文件的 inode)→ 比较前需明确语义 - 跨挂载点的同名 inode(如两个 ext4 分区各自 inode 123):
st_dev不同 → 必须同时校验st_dev,漏掉就错 - 权限不足导致
stat()失败(errno == EACCES),函数返回false,但这不代表“不是硬链接”,而是“无法判断”
std::filesystem 能否替代?
C++17 的 std::filesystem::status() 或 std::filesystem::symlink_status() 底层仍调用 stat() 或 lstat(),但标准未要求暴露 st_ino 和 st_dev。GCC libstdc++ 和 Clang libc++ 当前通过 std::filesystem::file_status::type() 无法提取 inode 信息,所以不能直接用于硬链接判断。
必须回退到 POSIX stat() 或平台特定 API(如 Linux 的 ioctl(fd, FS_IOC_GETFLAGS, ...) 不相关,别乱试)。
硬链接判定这件事,绕不开原始系统调用;封装层越厚,越容易丢掉关键字段。


















