最可靠的方式是调用 stat() 获取 st_dev 和 st_ino 并完全相等(Linux/macOS),或 GetFileInformationByHandle() 比较卷序列号与文件索引(Windows);跨平台应优先使用 std::filesystem::equivalent(),但需注意其受权限、符号链接策略及工作目录影响。

Linux/macOS 下用 stat() 比较 inode 和 device
最可靠的方式是调用 stat() 获取两个路径的 st_dev 和 st_ino,二者完全相等才代表同一物理文件。注意必须用 stat()(而非 lstat()),否则符号链接会被解析失败。
- 如果任一路径不存在或无权限访问,
stat()返回 -1,需提前检查errno - 跨文件系统时
st_dev必然不同,即使st_ino碰巧相同也无效 - 不要只比
st_ino—— 不同设备上 inode 号可重复
Windows 下用 GetFileInformationByHandle()
Windows 没有 inode 概念,需打开文件句柄后调用 GetFileInformationByHandle(),比较返回结构体中的 dwVolumeSerialNumber 和 nFileIndexLow/nFileIndexHigh。
- 必须用
GENERIC_READ权限打开(即使只读元数据),且路径需存在 - 若路径是目录,需加
FILE_FLAG_BACKUP_SEMANTICS标志才能成功打开 - 不能对符号链接本身调用(会解析到目标),如需判断链接文件是否相同,得先用
GetFinalPathNameByHandle()展开
跨平台封装时绕不开的几个坑
直接拼接字符串比较路径(如 std::filesystem::canonical())在多数场景下不等价于物理文件判等:软链接、挂载点、硬链接、大小写敏感/不敏感文件系统都会导致结果错误。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
-
std::filesystem::equivalent()是 C++17 提供的标准方案,底层已适配各平台,但 Windows 上要求 Vista+ 且某些网络路径可能失败 - 它内部仍依赖上述系统调用,所以同样受权限、符号链接解析策略影响
- 若路径含相对分量(如
"../a.txt"),equivalent()会先做路径归一化,但当前工作目录变化会影响结果
硬链接与符号链接的语义差异必须分清
硬链接共享同一 inode(Linux/macOS)或文件索引号(Windows),因此 stat() 或 GetFileInformationByHandle() 能正确识别;而符号链接是独立文件对象,其元数据和目标文件无关。
立即学习“C++免费学习笔记(深入)”;
- 两个符号链接指向同一目标,它们自身仍是不同文件 —— 判等结果为 false
- 若想判断“最终目标是否相同”,需递归解析符号链接(用
readlink()或CreateSymbolicLink()对应的解析 API),但要注意循环链接风险 - Windows 的 junction 和 symbolic link 行为不同,
GetFinalPathNameByHandle()对 junction 支持更好

















