zoukankan      html  css  js  c++  java
  • C语言实现文件类型统计函数

    #include<dirent.h>
    #include<limits.h>
    #include<sys/stat.h>
    #include<stdio.h>
    #include<unistd.h>
    #include<stdlib.h>
    #include<string.h>
    
    #define FTW_F        1        //标记非目录文件
    #define FTW_D        2        //标记目录文件
    #define FTW_DNR        3        //标记不可读目录
    #define FTW_NS        4        //标记不可获得stat的文件
    
    static char *fullpath;        //保存文件的全路径
    static size_t pathlen;        //保存文件的路径长度
    
    
    //定义处理文件的函数
    typedef int Myfunc(const char *,const struct stat*,int);
    static Myfunc myfunc;
    static int myftw(char *,Myfunc *);
    static int dopath(Myfunc *);
    char *path_alloc(size_t *size_t);
    
    /*
    nreg:普通文件的个数;    ndir: 目录文件的数量;    nblk:块特殊文件的数量
    nchr:字符特殊文件的数量    nfifo:管道特殊文件的数量
    nslink:符号连接特殊文件的数量;    nsock:套接字文件数量; ntot:总文件数量
    */
    static long nreg,ndir,nblk,nchr,nfifo,nslink,nsock,ntot;
    
    int main( int argc, char *argv[])
    {
        int ret;
    
        if(argc != 2)
        {
            printf("falut command input !
    ");
            exit(1);
        }
    
        //计算各类文件的个数
        ret = myftw(argv[1],myfunc);
    
        ntot = nreg + ndir + nblk + nchr + nfifo + nslink + nsock;
    
        //避免除以0
        if(ntot == 0)
        {
            ntot = 1;
        }
    
        printf("regular files = %7ld,%5.2f %%
    ",nreg,nreg*100.0 / ntot);
        printf("direciotn files = %7ld,%5.2f %%
    ",ndir,ndir*100.0 / ntot);
        printf("block special = %7ld,%5.2f %%
    ",nblk,nblk*100.0 / ntot);
        printf("char special = %7ld,%5.2f %%
    ",nchr,nchr*100.0 / ntot);
        printf("FIFOS  = %7ld,%5.2f %%
    ",nfifo,nfifo*100.0 / ntot);
        printf("symbolic links = %7ld,%5.2f %%
    ",nslink,nslink*100.0 / ntot);
        printf("sockers  = %7ld,%5.2f %%
    ",nsock,nsock*100.0 / ntot);
        
    }
    
    //处理pathname并保存在一个全局的字符数组中,调用dopath
    static int myftw(char *pathname,Myfunc *func)
    {
        //为保存路径的字符串数组分配空间
        fullpath = path_alloc(&pathlen);
        
        //如果分配内存空间不够就重新分配
        if(pathlen <= strlen(pathname))
        {
            pathlen = strlen(pathname) * 2;
            if((fullpath = realloc(fullpath,pathlen )) == NULL);
                printf("realloc failed
    ");
        }
        //将路径名参数保存到全路径中,fullpath是全局变量,dopath函数可以调用
        strcpy(fullpath,pathname);
        
        return (dopath(func));
    }
    
    //路径数组分配
    char *path_alloc(size_t *size)
    {
        char *p = NULL;
        if(!size)
            return NULL;
        p = malloc(256);
        if(p)
            *size = 256;
        else
            *size = 0;
    
        return p;
    }
    
    //dopath用于判断是否是目录,然后根据选择情况是直接进入myfun函数取技术
    //还是递归调用dopath函数
    static int dopath(Myfunc *func)
    {
        struct stat        statbuf;
        struct dirent    *dirp;
        DIR             *dp;
        int             ret,n;
    
        //调用lstat获取路径名的stat信息,如果不成功,调用func函数,并传递给FTW_NS
        if(lstat(fullpath,&statbuf) < 0)
            return (func(fullpath, &statbuf, FTW_NS));
    
        //查看文件stat结构的st_mode,如果不是目录,调用func函数 
        //并传递给FTW_F,交由myfun进一步判断文件类型 
        if(S_ISDIR(statbuf.st_mode) == 0)
            return(func(fullpath,&statbuf,FTW_F));
        
        //最后一种情况就是该路径名代表的是一个目录,此次的fun的正常情况返回0
        //所以执行完func后还不会返回,会继续执行func
        if((ret = func(fullpath,&statbuf,FTW_D)) != 0)
            return(ret);
        
        //路径处理,扩充路径空间长度
        n = strlen(fullpath);
        if(n + NAME_MAX + 2 > pathlen)
        {
            pathlen *= 2;
            if((fullpath = realloc(fullpath,pathlen)) == NULL)
            {
                printf("realoc failed
    ");
            }
        }
        
        fullpath[n++] = '/';
        fullpath[n] = 0;
        
        //处理每个目录项
        if((dp = opendir(fullpath)) == NULL)
            return (func(fullpath,&statbuf,FTW_DNR));
        while((dirp = readdir(dp)) != NULL)
        {
            //忽略当前目录(.)和上一级目录(..)以避免进入死循环
            if(strcmp(dirp->d_name,".") == 0 ||     
                strcmp(dirp->d_name,"..") == 0 )
                continue;
            strcpy(&fullpath[n],dirp->d_name); //在“/”之后加上当前目录项的命中
    
            if((ret = dopath(func)) != 0) //然后采用新的路径名递递归的调用dopath
                break;
        }
    
        fullpath[n-1] = 0;
    
        //关闭目录
        if(closedir(dp) < 0 )
            printf("can't close directory %s",fullpath);
        
        return ret;
    
    }
    
    //通过stat结构的st_mode字段来判断文件的类型,并计数
    static int myfunc(const char *pathname,const struct stat *statptr,int type)
    {
        switch(type)
        {
            //会与非目录情况进行处理
            case FTW_F:
                switch (statptr->st_mode & S_IFMT)
                {
                    case S_IFREG:    nreg++;    break;
                    case S_IFBLK:    nblk++;    break;
                    case S_IFCHR:    nchr++;    break;
                    case S_IFIFO:    nfifo++;    break;
                    case S_IFLNK:     nslink++;    break;
                    case S_IFSOCK:    nsock++;     break;
                    case S_IFDIR:    
                            printf("for S_IFDIR for %s",pathname);
                }
                break;
                
            //对于目录文件进行处理
            case FTW_D:
                ndir++;
                break;
            //对于不可读目录进行处理
            case FTW_DNR:
                printf("%s dir isn't read",pathname);
                break;
            case FTW_NS:
                printf("%s stat error",pathname);
    
            default:
                printf("%d type aren't identified, path is %s",type,pathname);
        }
    
        return 0;
    }
  • 相关阅读:
    数据库操作,内外联查询,分组查询,嵌套查询,交叉查询,多表查询,语句小结
    重复控件Repeater和数据列表控件DataList
    网格视图控件GridView (2)
    用好VS2005之扩展membership服务(1)
    5.4 网格视图控件GridView (1)
    数据源控件
    ASP.NET程序中常用的三十三种代码
    在DataSet和DataReader之间选择
    自定义ASP.net 2.0 Membership的步骤,和entry 'AspNetSqlMembershipProvider' has already been added错误的解决
    INNER JOIN
  • 原文地址:https://www.cnblogs.com/wanghao-boke/p/11608159.html
Copyright © 2011-2022 走看看