linux

如何用copendir获取Linux目录属性

小樊
45
2025-06-26 03:15:22
栏目: 智能运维

在 Linux 系统中,opendir() 函数用于打开一个目录流,以便后续使用其他相关函数(如 readdir())读取目录中的内容。然而,opendir() 本身并不直接提供获取目录属性的功能。要获取目录的属性,可以使用 dirent 结构体结合其他系统调用或库函数。以下是几种常用的方法:

方法一:使用 stat() 函数

stat() 函数可以获取文件或目录的详细信息。通过传递目录路径给 stat(),可以获得包括权限、所有者、大小、修改时间等在内的多种属性。

示例代码:

#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <dirent.h>
#include <unistd.h>

int main() {
    DIR *dir = opendir(".");
    if (dir == NULL) {
        perror("opendir");
        return EXIT_FAILURE;
    }

    struct dirent *entry;
    while ((entry = readdir(dir)) != NULL) {
        if (entry->d_type == DT_DIR) { // 只处理目录
            char path[1024];
            snprintf(path, sizeof(path), "./%s", entry->d_name);

            struct stat st;
            if (stat(path, &st) == -1) {
                perror("stat");
                continue;
            }

            printf("目录名称: %s\n", entry->d_name);
            printf("大小: %ld 字节\n", st.st_size);
            printf("权限: ");
            printf((S_ISDIR(st.st_mode)) ? "d" : "-");
            printf((st.st_mode & S_IRUSR) ? "r" : "-");
            printf((st.st_mode & S_IWUSR) ? "w" : "-");
            printf((st.st_mode & S_IXUSR) ? "x" : "-");
            printf((st.st_mode & S_IRGRP) ? "r" : "-");
            printf((st.st_mode & S_IWGRP) ? "w" : "-");
            printf((st.st_mode & S_IXGRP) ? "x" : "-");
            printf((st.st_mode & S_IROTH) ? "r" : "-");
            printf((st.st_mode & S_IWOTH) ? "w" : "-");
            printf((st.st_mode & S_IXOTH) ? "x" : "-\n");

            printf("最后修改时间: %s", ctime(&st.st_mtime));
        }
    }

    closedir(dir);
    return EXIT_SUCCESS;
}

说明:

方法二:使用 dirent 结构体中的 d_type

从 Linux Kernel 2.6.15 开始,dirent 结构体新增了 d_type 字段,可以用来判断目录条目的类型(如文件、目录、符号链接等)。这使得无需调用 stat() 即可部分获取目录属性。

示例代码:

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

int main() {
    DIR *dir = opendir(".");
    if (dir == NULL) {
        perror("opendir");
        return EXIT_FAILURE;
    }

    struct dirent *entry;
    while ((entry = readdir(dir)) != NULL) {
        if (entry->d_type == DT_DIR) { // 只处理目录
            printf("目录名称: %s\n", entry->d_name);
        }
    }

    closedir(dir);
    return EXIT_SUCCESS;
}

说明:

方法三:使用 getdents() 系统调用

getdents() 是一个低级的系统调用,可以直接读取目录条目并获取更多信息,适用于需要高性能的场景。

示例代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <dirent.h>
#include <fcntl.h>
#include <unistd.h>

int main() {
    int fd = open(".", O_RDONLY);
    if (fd == -1) {
        perror("open");
        return EXIT_FAILURE;
    }

    struct dirent *buf = malloc(1024);
    if (buf == NULL) {
        perror("malloc");
        close(fd);
        return EXIT_FAILURE;
    }

    ssize_t n = syscall(SYS_getdents, fd, buf, sizeof(buf));
    if (n == -1) {
        perror("getdents");
        free(buf);
        close(fd);
        return EXIT_FAILURE;
    }

    for (ssize_t i = 0; i < n; ) {
        struct linux_dirent *de = (struct linux_dirent *)(buf + i);
        char path[1024];
        snprintf(path, sizeof(path), "./%s", de->d_name);

        if (de->d_type == DT_DIR) { // 只处理目录
            printf("目录名称: %s\n", de->d_name);
        }

        i += de->d_reclen;
    }

    free(buf);
    close(fd);
    return EXIT_SUCCESS;
}

说明:

注意:

总结

虽然 opendir() 本身只能用于打开目录流,但结合其他系统调用(如 stat())或利用 dirent 结构体中的新字段(如 d_type),可以实现获取目录属性的功能。选择具体方法时,应根据需求权衡性能和功能复杂度。

0
看了该问题的人还看了