用C语言实现统计一个文件夹中各种文件的比例

简介: 原文:用C语言实现统计一个文件夹中各种文件的比例  《UNIX环境高级编程》中的程序清单4-7就介绍了如何实现递归地统计某个目录下面的文件!我刚开始看过它的代码后,觉得照着敲太没意思了,所以就合上书自己写了一遍!为此还写了一篇博文,这是博文地址: 在linux下用C语言实现递归查看某个目录中的所有文件【CSDN】!   今天做《Unix环境高级编程》的课后题,看到题目4.11这里提供了一种新的实现这个程序的思路,那就是每回读到一个目录,就通过chdir函数进入到这个目录,然后再通过opendir函数和readdir函数来读取这个目录中的文件,然后一个一个分析,如果是目录,则进行递归调用。
原文: 用C语言实现统计一个文件夹中各种文件的比例

  《UNIX环境高级编程》中的程序清单4-7就介绍了如何实现递归地统计某个目录下面的文件!我刚开始看过它的代码后,觉得照着敲太没意思了,所以就合上书自己写了一遍!为此还写了一篇博文,这是博文地址: 在linux下用C语言实现递归查看某个目录中的所有文件【CSDN】!

  今天做《Unix环境高级编程》的课后题,看到题目4.11这里提供了一种新的实现这个程序的思路,那就是每回读到一个目录,就通过chdir函数进入到这个目录,然后再通过opendir函数和readdir函数来读取这个目录中的文件,然后一个一个分析,如果是目录,则进行递归调用。如果不是目录,则对这个文件进行计数后立刻返回!这样一个一个分析完目录中的所有文件之后再来进行一个chdir(".."),返回到上一级的目录。具体的实现代码如下:

  

  1 #include<stdio.h>
  2 #include<string.h>
  3 #include<stdlib.h>
  4 #include<errno.h>
  5 #include<linux/limits.h>
  6 #include<unistd.h>
  7 #include<sys/types.h>
  8 #include<sys/stat.h>
  9 #include<dirent.h>
 10 
 11 //所有函数的声明
 12 typedef int MyFunc(const char *,const struct stat*,int);
 13 static MyFunc myfunc;        //定义处理文件的函数
 14 static int myftw(const char *,MyFunc *);
 15 static int dopath(MyFunc *);
 16 
 17 //定义的全局变量
 18 static char *fullpath;    //存放文件的名称的变量
 19 static long sock_c,lnk_c,reg_c,blk_c,dir_c,chr_c,fifo_c,total_c;    //统计各种文件类型的数量
 20 
 21 //myfunc函数中需要定义的宏
 22 #define FTW_F 1        //文件类型是文件
 23 #define FTW_D 2        //文件类型是目录
 24 #define FTW_NS 3    //一个文件不能stat
 25 #define FTW_ND 4    //一个目录不能被读
 26 int main(int argc,char *argv[])
 27 {
 28     if(argc != 2)
 29     {
 30     printf("Usage:%s pathname\n",argv[0]+2);
 31     exit(EXIT_FAILURE);
 32     }
 33     myftw(argv[1],myfunc);
 34     total_c = sock_c+lnk_c+reg_c+blk_c+dir_c+chr_c+fifo_c;
 35     if(0 == total_c)
 36     {
 37     total_c = 1;
 38     }
 39     printf("socket files    = %7ld, %5.2f%%\n",sock_c,sock_c*100.0/total_c);
 40     printf("link files      = %7ld, %5.2f%%\n",lnk_c,lnk_c*100.0/total_c);
 41     printf("regular files   = %7ld, %5.2f%%\n",reg_c,reg_c*100.0/total_c);
 42     printf("block files     = %7ld, %5.2f%%\n",blk_c,blk_c*100.0/total_c);
 43     printf("directory files = %7ld, %5.2f%%\n",dir_c,dir_c*100.0/total_c);
 44     printf("character files = %7ld, %5.2f%%\n",chr_c,chr_c*100.0/total_c);
 45     printf("FIFO files      = %7ld, %5.2f%%\n",fifo_c,fifo_c*100.0/total_c);
 46     printf("total files     = %7ld, %5.2f%%\n",total_c,total_c*100.0/total_c);
 47 
 48     return 0;
 49 }
 50 static int myftw(const char* pathname,MyFunc *pmyfunc)
 51 {
 52     int ret;
 53 
 54     fullpath = (char *)malloc(sizeof(char)*PATH_MAX);
 55     strcpy(fullpath,pathname);
 56     ret = dopath(myfunc);
 57     free(fullpath);
 58 
 59     return ret;
 60 }
 61 static int dopath(MyFunc *pmyfunc)
 62 {
 63     int ret;
 64     struct stat statbuf;
 65     char *ptr;
 66     DIR *dp;
 67     struct dirent* dirp;
 68 
 69     if(-1 == lstat(fullpath,&statbuf))
 70     {
 71     ret = pmyfunc(fullpath,&statbuf,FTW_NS);
 72     return ret;
 73     }
 74     if(S_ISDIR(statbuf.st_mode) != 1)
 75     {
 76     ret = pmyfunc(fullpath,&statbuf,FTW_F);
 77     return ret;
 78     }
 79 
 80     //使目录文件++
 81     if(0 != (ret=pmyfunc(fullpath,&statbuf,FTW_D)))
 82     return ret;
 83 
 84     //如果是目录文件则进入这个目录
 85     if(-1 == chdir(fullpath))
 86     {
 87     printf("%s[chdir]%s\n",fullpath,strerror(errno));
 88     ret == -1;
 89     return ret;
 90     }
 91 
 92     //打开当前目录
 93     if(NULL == (dp=opendir(".")))
 94     {
 95     ret = pmyfunc(fullpath,&statbuf,FTW_ND);
 96     return ret;
 97     }
 98     while(NULL != (dirp=readdir(dp)))
 99     {
100     //忽略.和..文件(dot)
101     if(0==strcmp(dirp->d_name,".") || 0==strcmp(dirp->d_name,".."))
102         continue;
103     memset(fullpath,0,PATH_MAX);
104     strcpy(fullpath,dirp->d_name);
105 
106     if(0 != (ret=dopath(myfunc)))    //进行递归
107         break;
108     }
109     chdir("..");    //将当前目录设置为上一级目录
110     //对关闭文件进行判断
111     if(-1 == closedir(dp))
112     {
113     printf("不能关闭%s\nError:%s",fullpath,strerror(errno));
114     }
115 
116     return ret;
117 }
118 static int myfunc(const char * pathname,const struct stat * statptr,int type)
119 {
120     switch(type)
121     {
122     case FTW_F:
123     switch(statptr->st_mode & S_IFMT)
124     {
125     case S_IFSOCK:    sock_c++;    break;
126     case S_IFLNK:    lnk_c++;    break;
127     case S_IFREG:    reg_c++;    break;
128     case S_IFBLK:    blk_c++;    break;
129     case S_IFCHR:    chr_c++;    break;
130     case S_IFIFO:    fifo_c++;    break;
131     case S_IFDIR:
132         printf("Error:这里不应该出现目录文件%s!\n\nError:%s\n",pathname,strerror(errno));
133         break;
134     }
135     break;
136     case FTW_D:
137     dir_c++;    break;
138     case FTW_ND:
139     printf("不能打开目录%s\nError:%s\n",pathname,strerror(errno));
140     break;
141     case FTW_NS:
142     printf("不能打开文件%s\nError:%s\n",pathname,strerror(errno));
143     break;
144     }
145     return 0;
146 }

  我这个代码并不是我自己合上书写的,而是在W.Richard Stevens书中给出的代码的基础上改的!在此要特别感谢这些真正的大神给我们提供了这么优秀的书籍!这是这个程序的运行结果,

  那个第一行是我特意设置的,那个root是一个文件夹的名字,是属于root用户的,所以我这里并不能读取,会报出一个错误!下面是这个改进后的程序和原来书中的程序的一个对比,发现效率还真的是提高不少啊!

  那个descend_hierarchy_p的那个程序是书上给的程序,每回读取都是读取的绝对路径的名称!而那个descend_hierarchy_ch命令就是每回碰到一个目录就进入到那个文件夹中,然后再来读取,这样每回读取的时候读取的就是相对路径的名称了!

目录
相关文章
|
存储 编译器 程序员
c语言的文件操作与文件缓冲区
如果没有文件,我们写的程序的数据是存储在电脑的内存中,如果程序退出,内存回收,数据就丢失了,等再次运行程序,是看不到上次程序的数据的,如果要将数据进行持久化的保存,我们可以使用文件。磁盘(硬盘)上的文件是文件。但是在程序设计中,我们⼀般谈的⽂件有两种:程序文件、数据文件(从文件功能的角度来分类 的)。就比如说我们电脑中以.txt为后缀的就是文件的一种,他就是数据文件。.exe为后缀的就为程序文件。函数名功能适用范围fgetc字符输入函数所有输入流fputc字符输出函数所有输出流fgets。
493 0
|
人工智能 C语言
|
C语言
【C语言程序设计——循环程序设计】统计海军鸣放礼炮声数量(头歌实践教学平台习题)【合集】
有A、B、C三艘军舰同时开始鸣放礼炮各21响。已知A舰每隔5秒1次,B舰每隔6秒放1次,C舰每隔7秒放1次。编程计算观众总共听到几次礼炮声。根据提示,在右侧编辑器Begin--End之间的区域内补充必要的代码。开始你的任务吧,祝你成功!
367 13
|
存储 小程序 C语言
【C语言程序设计——文件】文件操作(头歌实践教学平台习题)【合集】
本文介绍了C语言中的文件操作,分为两个关卡。第1关任务是将键盘输入的字符(以#结束)存入`file1.txt`并显示输出;第2关任务是从键盘输入若干行文本(每行不超过80个字符,用-1作为结束标志),写入`file2.txt`后再读取并显示。文中详细讲解了文件的打开、读取(使用`fgetc()`和`fgets()`)、写入(使用`fputc()`和`fputs()`)及关闭操作,并提供了示例代码和测试说明。
512 5
|
算法 C语言
C语言中的文件操作技巧,涵盖文件的打开与关闭、读取与写入、文件指针移动及注意事项
本文深入讲解了C语言中的文件操作技巧,涵盖文件的打开与关闭、读取与写入、文件指针移动及注意事项,通过实例演示了文件操作的基本流程,帮助读者掌握这一重要技能,提升程序开发能力。
945 3
|
存储 编译器 C语言
如何在 C 语言中判断文件缓冲区是否需要刷新?
在C语言中,可以通过检查文件流的内部状态或使用`fflush`函数尝试刷新缓冲区来判断文件缓冲区是否需要刷新。通常,当缓冲区满、遇到换行符或显式调用`fflush`时,缓冲区会自动刷新。
|
存储 编译器 C语言
C语言:文件缓冲区刷新方式有几种
C语言中文件缓冲区的刷新方式主要包括三种:自动刷新(如遇到换行符或缓冲区满)、显式调用 fflush() 函数强制刷新、以及关闭文件时自动刷新。这些方法确保数据及时写入文件。
|
C语言
【C语言】探索文件读写函数的全貌(三)
【C语言】探索文件读写函数的全貌
154 2
|
存储 C语言
【C语言】探索文件读写函数的全貌(二)
【C语言】探索文件读写函数的全貌
199 2
|
Linux C语言
C语言 文件IO (系统调用)
本文介绍了Linux系统调用中的文件I/O操作,包括文件描述符、`open`、`read`、`write`、`lseek`、`close`、`dup`、`dup2`等函数,以及如何获取文件属性信息(`stat`)、用户信息(`getpwuid`)和组信息(`getgrgid`)。此外还介绍了目录操作函数如`opendir`、`readdir`、`rewinddir`和`closedir`,并提供了相关示例代码。系统调用直接与内核交互,没有缓冲机制,效率相对较低,但实时性更高。