溫馨提示×

如何用copendir實現Linux目錄的篩選遍歷

小樊
44
2025-03-31 08:38:21
欄目: 智能運維

在Linux中,opendir、readdir等函數常用于遍歷目錄。如果你想要在遍歷過程中篩選出特定類型的文件或目錄,可以在讀取每個條目后進行檢查。以下是一個使用C語言和這些函數實現目錄篩選遍歷的示例:

示例代碼

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

// 函數:檢查路徑是否為指定類型的文件或目錄
int is_type(const char *path, const char *type) {
    if (strcmp(type, "all") == 0) {
        return 1; // 不限制類型
    }

    char ext[10];
    // 獲取文件擴展名
    const char *dot = strrchr(path, '.');
    if (dot && dot > path) {
        size_t len = dot - path;
        if (len >= sizeof(ext)) {
            len = sizeof(ext) - 1;
        }
        strncpy(ext, path, len);
        ext[len] = '\0';
    } else {
        strcpy(ext, "");
    }

    return strcmp(ext, type) == 0;
}

// 函數:遞歸遍歷目錄
void traverse_directory(const char *path, const char *filter) {
    DIR *dir = opendir(path);
    if (dir == NULL) {
        perror("opendir");
        return;
    }

    struct dirent *entry;
    while ((entry = readdir(dir)) != NULL) {
        // 跳過當前目錄和上級目錄
        if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
            continue;
        }

        // 構建完整路徑
        char full_path[PATH_MAX];
        snprintf(full_path, sizeof(full_path), "%s/%s", path, entry->d_name);

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

        // 如果是目錄,遞歸遍歷
        if (S_ISDIR(st.st_mode)) {
            traverse_directory(full_path, filter);
        }
        // 如果是文件,根據過濾器決定是否處理
        else if (S_ISREG(st.st_mode)) {
            if (is_type(full_path, filter)) {
                printf("文件: %s\n", full_path);
            }
        }
    }

    closedir(dir);
}

int main(int argc, char *argv[]) {
    if (argc != 3) {
        fprintf(stderr, "用法: %s <目錄路徑> <過濾器>\n", argv[0]);
        fprintf(stderr, "過濾器示例:\n");
        fprintf(stderr, "  all           - 所有文件和目錄\n");
        fprintf(stderr, "  .txt          - 僅.txt文件\n");
        fprintf(stderr, "  .jpg,.png     - 僅.jpg和.png圖片文件\n");
        return EXIT_FAILURE;
    }

    const char *directory = argv[1];
    const char *filter = argv[2];

    traverse_directory(directory, filter);

    return EXIT_SUCCESS;
}

代碼說明

  1. 函數 is_type:

    • 用于檢查文件路徑是否符合指定的類型。
    • 支持通配符,例如 .txt.jpg,.png。
    • 如果過濾器為 "all",則不過濾任何文件。
  2. 函數 traverse_directory:

    • 使用 opendir 打開指定目錄。
    • 使用 readdir 讀取目錄中的每個條目。
    • 跳過當前目錄 (.) 和上級目錄 (..)。
    • 使用 stat 獲取文件的狀態信息,判斷是文件還是目錄。
    • 如果是目錄,遞歸調用 traverse_directory。
    • 如果是文件,調用 is_type 判斷是否符合過濾器,若符合則打印路徑。
  3. main 函數:

    • 接受兩個命令行參數:要遍歷的目錄路徑和過濾器。
    • 調用 traverse_directory 開始遍歷。

編譯和運行

假設將上述代碼保存為 dir_traverse.c,可以使用以下命令編譯:

gcc -o dir_traverse dir_traverse.c

然后運行程序,例如:

./dir_traverse /path/to/directory txt

這將遍歷 /path/to/directory 目錄及其子目錄,打印所有擴展名為 .txt 的文件。

進一步優化

  • 支持更多通配符: 可以擴展 is_type 函數,使其支持更復雜的模式匹配,如 *.jpg|*.png。
  • 錯誤處理: 增強錯誤處理機制,例如處理權限不足的情況。
  • 多線程遍歷: 對于大型目錄結構,可以考慮使用多線程來提高遍歷速度。

使用其他編程語言

如果你更習慣使用其他編程語言,如Python,也可以實現類似的功能。例如,使用 osfnmatch 模塊:

import os
import fnmatch

def traverse_directory(path, pattern):
    for root, dirs, files in os.walk(path):
        # 篩選目錄
        dirs[:] = [d for d in dirs if fnmatch.fnmatch(d, pattern)]
        # 篩選文件
        for filename in fnmatch.filter(files, pattern):
            print(os.path.join(root, filename))

if __name__ == "__main__":
    import sys
    if len(sys.argv) != 3:
        print("用法: python dir_traverse.py <目錄路徑> <過濾器>")
        sys.exit(1)
    directory = sys.argv[1]
    pattern = sys.argv[2]
    traverse_directory(directory, pattern)

這個Python腳本同樣接受目錄路徑和過濾器作為參數,使用 os.walk 遍歷目錄并使用 fnmatch 進行篩選。

希望這些示例對你有所幫助!

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