温馨提示×

linux readdir怎么处理符号链接

小樊
37
2026-09-26 20:21:43
栏目: 智能运维

在 Linux 下使用 readdir() 读取目录时,符号链接(symbolic link)本身并不会被自动展开,readdir() 只是返回目录项(dirent),其中包含文件类型信息。是否“处理”符号链接,取决于你后续怎么做。

下面分几个层面说明。


一、readdir() 本身与符号链接

readdir() 返回的是 struct dirent *:

struct dirent {
    ino_t          d_ino;
    off_t          d_off;
    unsigned short d_reclen;
    unsigned char  d_type;
    char           d_name[256];
};

关键点

  • d_type 可以告诉你文件类型
  • 符号链接的 d_type 是:
    DT_LNK
    

示例:

#include <dirent.h>
#include <stdio.h>

int main(int argc, char *argv[]) {
    DIR *dir = opendir(argv[1]);
    struct dirent *entry;

    while ((entry = readdir(dir)) != NULL) {
        if (entry->d_type == DT_LNK) {
            printf("symbolic link: %s\n", entry->d_name);
        }
    }
    closedir(dir);
    return 0;
}

✅ 这样你可以识别符号链接,但不会跟随它。


二、是否“跟随”符号链接(关键区别)

1️⃣ 不跟随符号链接(默认行为)

  • readdir()
  • lstat()

这些操作只看到符号链接本身

lstat(path, &sb);
// sb.st_mode 中 S_ISLNK(sb.st_mode) 为真

2️⃣ 跟随符号链接

如果你用:

  • stat()
  • open()
  • access()

那么会自动跟随符号链接,看到的是链接指向的目标。

struct stat sb;
stat(path, &sb); // 跟随符号链接

三、递归遍历目录时如何处理符号链接(常见需求)

问题

递归遍历目录时,如果不处理符号链接:

  • 可能无限循环(链接指向父目录)
  • 可能重复访问文件

推荐做法

✅ 方法 1:跳过符号链接

if (entry->d_type == DT_LNK)
    continue;

✅ 方法 2:只跳过“指向目录”的符号链接

struct stat sb;
lstat(path, &sb);
if (S_ISLNK(sb.st_mode)) {
    stat(path, &sb);
    if (S_ISDIR(sb.st_mode))
        continue;
}

✅ 方法 3:记录 inode 防止循环(更严谨)

dev_t dev;
ino_t ino;
stat(path, &sb);
// 用 (dev, ino) 做已访问集合

四、读取符号链接指向的内容

如果想知道符号链接指向哪里:

char buf[PATH_MAX];
ssize_t len = readlink(path, buf, sizeof(buf) - 1);
buf[len] = '\0';
printf("links to: %s\n", buf);

⚠️ readlink() 不会追加 \0,需要手动处理。


五、总结

操作 是否处理符号链接
readdir() 只列出,不展开
lstat() 看链接本身
stat() 跟随链接
readlink() 获取链接目标
递归遍历 建议显式跳过或防环

如果你愿意,我可以给你一个完整的“安全递归遍历目录”示例(C 语言),或者讲 fts / nftw 怎么自动处理符号链接。

0 踩