• 用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
    ",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%%
    ",sock_c,sock_c*100.0/total_c);
     40     printf("link files      = %7ld, %5.2f%%
    ",lnk_c,lnk_c*100.0/total_c);
     41     printf("regular files   = %7ld, %5.2f%%
    ",reg_c,reg_c*100.0/total_c);
     42     printf("block files     = %7ld, %5.2f%%
    ",blk_c,blk_c*100.0/total_c);
     43     printf("directory files = %7ld, %5.2f%%
    ",dir_c,dir_c*100.0/total_c);
     44     printf("character files = %7ld, %5.2f%%
    ",chr_c,chr_c*100.0/total_c);
     45     printf("FIFO files      = %7ld, %5.2f%%
    ",fifo_c,fifo_c*100.0/total_c);
     46     printf("total files     = %7ld, %5.2f%%
    ",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
    ",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
    Error:%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!
    
    Error:%s
    ",pathname,strerror(errno));
    133         break;
    134     }
    135     break;
    136     case FTW_D:
    137     dir_c++;    break;
    138     case FTW_ND:
    139     printf("不能打开目录%s
    Error:%s
    ",pathname,strerror(errno));
    140     break;
    141     case FTW_NS:
    142     printf("不能打开文件%s
    Error:%s
    ",pathname,strerror(errno));
    143     break;
    144     }
    145     return 0;
    146 }

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

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

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

  • 相关阅读:
    Git fetch和git pull的区别
    gitlab数据迁移
    阿里云CentOS7挂载SSD云盘的方法
    phpQuery的用法
    用shell查找某目录下的最大文件
    gearman 简介
    学习笔记(3)——实验室集群WMS服务配置
    学习笔记(2)——实验室集群LVS配置
    Fedora16的双显卡切换问题
    学习笔记(1)——实验室集群配置
  • 原文地址:https://www.cnblogs.com/bwangel23/p/4121741.html
Copyright © 2020-2023  润新知