You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何递归遍历文件夹并统计文件总大小?代码实现遇阻求助

解决递归文件夹文件大小统计问题

嘿,我来帮你搞定这个文件大小统计的问题!你现在遇到两个核心困扰:非递归模式下统计结果不准,还有递归遍历文件夹的逻辑没捋顺。咱们一步步拆解解决:

先排查非递归统计不准的原因

非递归统计出错,大概率是踩了这几个坑:

  • 没跳过.和..这两个特殊目录项,导致重复统计或者逻辑混乱
  • 误把目录本身的大小算进了总文件大小(目录也是一种文件,但我们要统计的是它内部的文件)
  • 没区分stat()和lstat()的差异:stat()会跟随符号链接到目标文件,lstat()只统计链接本身的大小,选不对就会出现大小偏差
  • 缺少错误处理:比如某个文件/目录无法访问时直接跳过,没做任何处理,导致统计遗漏

递归逻辑的核心实现思路

递归遍历的逻辑其实很清晰,就是「遇到目录就进去重复当前操作」:

  1. 打开目标目录,获取目录句柄
  2. 遍历目录下的每个条目
  3. 对每个条目做判断:
    • 如果是普通文件:调用stat()/lstat()获取大小,累加到总大小
    • 如果是目录(且不是./..):递归调用同一个统计函数处理这个子目录,把返回的子目录总大小加进来
  4. 遍历结束后关闭目录句柄,返回累加的总大小

完整可运行的示例代码

下面是包含递归逻辑、错误处理,且能准确统计的完整代码:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <string.h>
#include <errno.h>
#include <limits.h> // 包含PATH_MAX定义

// 递归计算目录及其子目录下所有普通文件的总大小
off_t calculate_total_size(const char *path) {
    off_t total = 0;
    DIR *dir = opendir(path);
    
    // 处理目录打开失败的情况
    if (!dir) {
        fprintf(stderr, "⚠️ 无法打开目录 %s: %s\n", path, strerror(errno));
        return 0;
    }

    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;
        // 用lstat避免跟随符号链接,若需要统计链接指向的文件大小,替换为stat即可
        if (lstat(full_path, &st) == -1) {
            fprintf(stderr, "⚠️ 无法获取文件信息 %s: %s\n", full_path, strerror(errno));
            continue;
        }

        if (S_ISREG(st.st_mode)) {
            // 普通文件,累加大小
            total += st.st_size;
        } else if (S_ISDIR(st.st_mode)) {
            // 子目录,递归计算其内部文件总大小
            total += calculate_total_size(full_path);
        }
        // 若需要统计其他类型文件(比如符号链接、设备文件),可添加对应的判断分支
    }

    closedir(dir);
    return total;
}

int main(int argc, char *argv[]) {
    if (argc != 2) {
        fprintf(stderr, "用法: %s <目标目录路径>\n", argv[0]);
        return 1;
    }

    off_t total_size = calculate_total_size(argv[1]);
    printf("✅ 总文件大小: %lld 字节\n", (long long)total_size);
    return 0;
}

关键细节说明

  • 路径拼接:用snprintf和PATH_MAX确保路径不会溢出,避免内存错误
  • 错误处理:每个系统调用(opendir、lstat)都做了错误捕获,避免程序崩溃,同时给出明确的错误提示
  • 符号链接处理:默认用lstat统计链接本身,若需要统计链接指向的文件,替换为stat即可
  • 非递归修正:如果要改成非递归版本,只需要把递归调用换成用栈/队列存储待处理的目录路径,逻辑和递归一致,只是用循环代替函数递归

内容的提问来源于stack exchange,提问作者user9443617

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 09:50:50