linux

如何用copendir实现Linux目录的筛选遍历

小樊
44
2025-03-31 08:38:21
栏目: 智能运维

在Linux中,opendirreaddir等函数常用于遍历目录。如果你想要在遍历过程中筛选出特定类型的文件或目录,可以在读取每个条目后进行检查。以下是一个使用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 的文件。

进一步优化

使用其他编程语言

如果你更习惯使用其他编程语言,如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
看了该问题的人还看了