logo头像

不忘初心,奋力前行

递归读目录获取普通文件个数

本文于372天之前发表,文中内容可能已经过时,如有问题,请联系我。

递归读目录获取普通文件个数

功能说明

递归进入当前目录及其子目录,遇到普通文件就对计数加1,遇到目录就进入目录,但并不做加1操作,最后输出普通文件个数。

使用的函数

1.opendir()函数:打开一个目录
2.readdir()函数:读目录。这个函数为核心,判断当前目录是否是普通文件,根据其返回的结构体中的d_type来进行判断。
3.closedir()函数:关闭目录。

使用到的头文件

对每个函数使用man命令查看帮助,或者在.c文件中将光标放在该函数名上,按shift+k也可以查看帮助。

1
2
3
4
#include <sys/types.h>//opendir、closedir使用
#include <dirent.h>//opendir、closedir使用
#include <stdio.h>
#include <stdlib.h>

打开目录、遍历目录和关闭目录

打开目录
打开目录类似于打开文件,同样需要对是否出现错误进行判断,若出现错误则输出错误信息,然后退出。

1
2
3
4
5
6
7
8
//打开目录
DIR* dir = NULL;
dir = opendir(root);
if(dir == NULL)
{
perror("Open dir error:");
exit(1);
}

遍历目录

由于readdir()函数的返回值是一个结构体,且当文件已经读完的时候返回NULL,因此可以利用是否返回NULL来作为判断循环结束的条件。

1
2
3
4
5
struct dirent* dr = NULL;
while((dr = readdir(dir))!= NULL)
{
...
}

关闭目录
直接执行关闭目录即可:

1
closeret = closedir(dir);

设计程序的时候的注意事项

  • 在读到普通目录的时候,我们要进入子目录,但是若读到.(当前目录)和..(上一级目录),我们就需要将它们排除在外。其原理就是使用strcmp()函数判断当前的名称是否是.或者..,若是则直接跳过,进行下一次循环。实现如下:
1
2
3
4
if(strcmp(dr->d_name, ".") == 0 || strcmp(dr->d_name, "..") == 0 )
{
continue;
}
  • 读普通目录,进入子目录进行递归计数。子目录的文件名需要我们进行拼接,也就是使用sprintf()函数。代码如下:
1
2
3
4
5
6
if(dr->d_type == DT_DIR)
{
//递归读目录
sprintf(path,"%s/%s",root,dr->d_name);
total += getFileNum(path);
}
  • 对于遇到普通文件,则直接对total进行+1,实现如下:
1
2
3
4
if(dr->d_type == DT_REG)
{
total++;
}

完整代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <dirent.h>

int getFileNum(char* root)
{
//打开目录
DIR* dir = NULL;
dir = opendir(root);
if(dir == NULL)
{
perror("Open dir error:");
exit(1);
}
int total=0;
//遍历当前目录
struct dirent* dr = NULL;
char path[1024] = {0};
while((dr = readdir(dir))!= NULL)
{
//过滤.和..
if(strcmp(dr->d_name, ".") == 0 || strcmp(dr->d_name, "..") == 0 )
{
continue;
}
//遇到目录,进入目录
if(dr->d_type == DT_DIR)
{
//递归读目录
sprintf(path,"%s/%s",root,dr->d_name);
total += getFileNum(path);
}
//如果是普通文件
if(dr->d_type == DT_REG)
{
total++;
}
}
//关闭目录
int closeret = closedir(dir);
if(closeret == -1)
{
perror("Close File error:");
exit(1);
}
return total;
}
int main(int argc, char* argv[])
{
if(argc<2)
{
printf("Usage: ./filecount <dir>\n");
exit(1);
}

int result = getFileNum(argv[1]);
printf("目录 %s 共有普通文件 %d 个\n",argv[1],result);
return 0;
}

实现结果

支付宝打赏 微信打赏 QQ钱包打赏

感觉不错?欢迎给我 打个赏~我将不胜感激!