递归遍历目录统计总文件大小遇阻:代码参数与total变量问题求助
解决递归遍历目录统计文件总大小的问题
看起来你在实现递归遍历目录并统计文件总大小时遇到了两个核心问题:递归调用的参数传递错误,以及总大小统计不正确。我来帮你拆解问题并给出修正方案。
核心问题分析
- 递归路径传递错误:如果你的
do_ls函数只传入子目录/文件的名称(而非完整路径),那么当程序进入子目录后,无法正确定位到文件——因为进程的当前工作目录并没有改变,直接用子文件名调用stat会找不到文件,自然无法统计大小。 - 全局变量与逻辑漏洞:虽然全局变量
total本身没问题,但如果路径错误导致大量文件的stat调用失败,或者没有正确区分普通文件和目录(比如把目录本身的大小也算进去),就会导致最终总大小不正确。另外,全局变量在多线程场景下不安全,更推荐用指针传递的方式维护总大小。
修正后的完整代码
下面是修复后的代码,解决了上述问题,同时增加了错误处理和更安全的路径拼接:
#include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <dirent.h> #include <string.h> #include <stdlib.h> #include <limits.h> // 引入PATH_MAX定义 // 用指针传递总大小,替代全局变量,更符合模块化编程 void do_ls(const char *path, long long *total) { // 打开目标目录 DIR *dir = opendir(path); if (!dir) { perror("Failed to open directory"); return; } struct dirent *entry; char full_path[PATH_MAX]; // 存储拼接后的完整路径 while ((entry = readdir(dir)) != NULL) { // 跳过当前目录(.)和父目录(..),避免无限递归 if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) { continue; } // 安全拼接完整路径:用snprintf避免缓冲区溢出 snprintf(full_path, sizeof(full_path), "%s/%s", path, entry->d_name); struct stat stat_buf; // 获取文件/目录的属性信息 if (stat(full_path, &stat_buf) == -1) { perror("Failed to get file status"); continue; } // 如果是普通文件,累加其大小到总大小 if (S_ISREG(stat_buf.st_mode)) { printf("File: %s, Size: %lld bytes\n", full_path, (long long)stat_buf.st_size); *total += stat_buf.st_size; } // 如果是目录,递归遍历该子目录 else if (S_ISDIR(stat_buf.st_mode)) { do_ls(full_path, total); } } closedir(dir); } int main(int argc, char *argv[]) { // 默认遍历当前目录,也可以通过命令行参数指定起始目录 const char *start_path = argc > 1 ? argv[1] : "."; long long total = 0; do_ls(start_path, &total); printf("\nTotal size of all files: %lld bytes\n", total); return 0; }
关键修正点说明
- 完整路径传递:递归调用
do_ls时,传入的是拼接后的full_path,确保stat能正确找到目标文件/目录。 - 替代全局变量:用指针
*total传递总大小,避免全局变量带来的副作用,同时让函数更独立。 - 安全路径拼接:使用
snprintf而非strcat,可以避免路径过长导致的缓冲区溢出问题。 - 错误处理:对
opendir和stat的失败情况打印错误信息,方便排查哪些文件/目录无法访问。 - 跳过特殊目录:必须跳过
.和..,否则会陷入无限递归(比如反复进入当前目录)。 - 区分文件类型:只统计普通文件(
S_ISREG)的大小,目录本身的st_size是目录项的存储大小,不是目录下文件的总大小,所以不能累加。
编译与运行
你可以用gcc编译这段代码:
gcc dir_size.c -o dir_size
运行时可以指定目录,比如统计当前目录:
./dir_size
或者指定某个具体目录:
./dir_size /home/yourname/documents
内容的提问来源于stack exchange,提问作者user9443617
相关产品推荐
相关产品推荐

