溫馨提示×

如何用copendir獲取Linux目錄屬性

小樊
53
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;
}

說明:

  • opendir(".") 打開當前目錄。
  • readdir(dir) 讀取目錄中的每一個條目。
  • 對于每個目錄條目,使用 snprintf() 構建完整的路徑。
  • stat(path, &st) 獲取該路徑的詳細信息,并存儲在 struct stat 結構體中。
  • 根據 st.st_mode 的值,打印目錄的權限和其他屬性。

方法二:使用 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;
}

說明:

  • d_type 可以是 DT_REG(常規文件)、DT_DIR(目錄)、DT_LNK(符號鏈接)等。
  • 這種方法比調用 stat() 更高效,但功能較為有限,無法獲取詳細屬性。

方法三:使用 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;
}

說明:

  • 使用 open() 打開目錄。
  • 分配緩沖區并通過 syscall(SYS_getdents, ...) 讀取目錄條目。
  • 遍歷緩沖區中的每個 linux_dirent 結構體,判斷類型并處理。

注意:

  • getdents() 是一個低級接口,通常需要包含 <linux/dirent.h> 并使用特定的結構體 linux_dirent,這在不同的 Linux 版本中可能有所不同。
  • 該方法適用于需要高性能的場景,但編程復雜度較高。

總結

雖然 opendir() 本身只能用于打開目錄流,但結合其他系統調用(如 stat())或利用 dirent 結構體中的新字段(如 d_type),可以實現獲取目錄屬性的功能。選擇具體方法時,應根據需求權衡性能和功能復雜度。

0
亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女