递归读目录获取普通文件个数
功能说明
递归进入当前目录及其子目录,遇到普通文件就对计数加1,遇到目录就进入目录,但并不做加1操作,最后输出普通文件个数。
使用的函数
1.opendir()函数:打开一个目录
2.readdir()函数:读目录。这个函数为核心,判断当前目录是否是普通文件,根据其返回的结构体中的d_type
来进行判断。
3.closedir()函数:关闭目录。
使用到的头文件
对每个函数使用man
命令查看帮助,或者在.c
文件中将光标放在该函数名上,按shift+k
也可以查看帮助。
1 2 3 4 5 |
#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 9 |
//打开目录 DIR* dir = NULL; dir = opendir(root); if(dir == NULL) { perror("Open dir error:"); exit(1); } |
遍历目录
由于readdir()
函数的返回值是一个结构体,且当文件已经读完的时候返回NULL
,因此可以利用是否返回NULL来作为判断循环结束的条件。
1 2 3 4 5 6 |
struct dirent* dr = NULL; while((dr = readdir(dir))!= NULL) { ... } |
关闭目录
直接执行关闭目录即可:
1 2 |
closeret = closedir(dir); |
设计程序的时候的注意事项
- 在读到普通目录的时候,我们要进入子目录,但是若读到
.
(当前目录)和..
(上一级目录),我们就需要将它们排除在外。其原理就是使用strcmp()
函数判断当前的名称是否是.
或者..
,若是则直接跳过,进行下一次循环。实现如下:
1 2 3 4 5 |
if(strcmp(dr->d_name, ".") == 0 || strcmp(dr->d_name, "..") == 0 ) { continue; } |
- 读普通目录,进入子目录进行递归计数。子目录的文件名需要我们进行拼接,也就是使用
sprintf()
函数。代码如下:
1 2 3 4 5 6 7 |
if(dr->d_type == DT_DIR) { //递归读目录 sprintf(path,"%s/%s",root,dr->d_name); total += getFileNum(path); } |
- 对于遇到普通文件,则直接对total进行+1,实现如下:
1 2 3 4 5 |
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 61 |
#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; } |