插件窝 干货文章 如何用copendir实现递归目录遍历

如何用copendir实现递归目录遍历

目录 path include listFilesRecursi 745    来源:    2025-05-05

使用 copendir 实现递归目录遍历

copendir 是 C 语言中用于打开目录的函数(实际上是 opendir,可能是拼写错误)。下面我将介绍如何使用 opendir 结合其他目录操作函数实现递归目录遍历。

基本实现方法

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

void listFilesRecursively(const char *basePath) {
    char path[1000];
    struct dirent *dp;
    struct stat statbuf;
    DIR *dir = opendir(basePath);

    // 无法打开目录则返回
    if (!dir) {
        perror("opendir failed");
        return;
    }

    while ((dp = readdir(dir)) != NULL) {
        // 跳过当前目录和上级目录
        if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0) {
            continue;
        }

        // 构建完整路径
        snprintf(path, sizeof(path), "%s/%s", basePath, dp->d_name);

        // 获取文件信息
        if (stat(path, &statbuf) == -1) {
            perror("stat failed");
            continue;
        }

        // 如果是目录,递归调用
        if (S_ISDIR(statbuf.st_mode)) {
            printf("目录: %s\n", path);
            listFilesRecursively(path);
        } else {
            printf("文件: %s\n", path);
        }
    }

    closedir(dir);
}

int main() {
    listFilesRecursively(".");  // 从当前目录开始遍历
    return 0;
}

关键函数说明

  1. opendir(const char *name) - 打开目录,返回 DIR* 指针
  2. readdir(DIR *dirp) - 读取目录中的条目
  3. closedir(DIR *dirp) - 关闭目录
  4. stat(const char *path, struct stat *buf) - 获取文件状态信息

改进版本(更健壮的实现)

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

#define MAX_PATH_LEN 4096

void listFilesRecursively(const char *basePath) {
    char path[MAX_PATH_LEN];
    struct dirent *dp;
    struct stat statbuf;
    DIR *dir;

    if ((dir = opendir(basePath)) == NULL) {
        fprintf(stderr, "无法打开目录 %s: %s\n", basePath, strerror(errno));
        return;
    }

    while ((dp = readdir(dir)) != NULL) {
        if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0) {
            continue;
        }

        if (snprintf(path, MAX_PATH_LEN, "%s/%s", basePath, dp->d_name) >= MAX_PATH_LEN) {
            fprintf(stderr, "路径过长: %s/%s\n", basePath, dp->d_name);
            continue;
        }

        if (lstat(path, &statbuf) == -1) {
            fprintf(stderr, "无法获取 %s 的状态: %s\n", path, strerror(errno));
            continue;
        }

        if (S_ISDIR(statbuf.st_mode)) {
            printf("目录: %s\n", path);
            listFilesRecursively(path);
        } else {
            printf("文件: %s\n", path);
        }
    }

    if (closedir(dir) == -1) {
        fprintf(stderr, "关闭目录 %s 失败: %s\n", basePath, strerror(errno));
    }
}

int main(int argc, char *argv[]) {
    const char *path = argc > 1 ? argv[1] : ".";
    listFilesRecursively(path);
    return 0;
}

注意事项

  1. 路径长度限制:使用固定大小的缓冲区时要注意路径长度限制
  2. 符号链接:上面的代码使用 lstat 而不是 stat 以避免跟随符号链接
  3. 错误处理:增加了更详细的错误处理
  4. 权限问题:程序需要有足够的权限访问目录和文件

替代方案

如果你使用的是 C++,可以考虑使用 <filesystem> 库(C++17 引入),它提供了更简单的方式来实现递归目录遍历:

#include <filesystem>
#include <iostream>

namespace fs = std::filesystem;

void listFilesRecursively(const fs::path& path) {
    for (const auto& entry : fs::recursive_directory_iterator(path)) {
        std::cout << (entry.is_directory() ? "目录: " : "文件: ") 
                  << entry.path() << std::endl;
    }
}

int main() {
    listFilesRecursively(".");
    return 0;
}

希望这个实现对你有所帮助!如果需要针对特定场景的定制版本,可以提供更多需求细节。