zoukankan      html  css  js  c++  java
  • 【C】——APUE小程序之递归遍历目录

      递归降序遍历目录层次结构,并按文件类型计数。

      先介绍相关的函数:

    #include<dirent.h>
    
    DIR *opendir(const char *pathname);        //打开目录
    返回值:成功返回指针,出错返回NULL
    
    struct dirent *readdir(DIR *dp);               //读取目录       
    返回值:成功返回指针,出错返回NULL
    
    void rewinddir(DIR *dp);                           //重设读取目录的位置为开头位置
    
    int closedir(DIR *dp);                             //关闭目录       
    返回值:成功返回0,出错返回-1
    
    long telldir(DIR *dp);                            //取得目录流的读取位置   
    返回值:与dp关联的目录中的当前位置
    
    void seekdir(DIR *dp, long loc);              //设置下回读取目录的位置
    
    struct dirent{
         ino_t d_ino;                         //i-node number
         char   d_name[NAME_MAX + 1];            //null-terminated filename
    }

      改写APUE的代码:

      1 #include<stdio.h>
      2 #include<dirent.h>
      3 #include<sys/stat.h>
      4 #include<string.h>
      5 #include<stdlib.h>
      6 
      7 static int nreg = 0, ndir = 0, nblk = 0, nchr = 0, nfifo = 0, nslink = 0, nsock = 0, ntot = 0;
      8 
      9 static char *fullpath;
     10 
     11 int myfunc(const char *pathname, const struct stat *statptr, int type)
     12 {
     13     switch(type){
     14     case 1:
     15         switch(statptr->st_mode & S_IFMT){
     16         case S_IFREG: nreg++;    break;
     17         case S_IFBLK: nblk++;    break;
     18         case S_IFCHR: nchr++;    break;
     19         case S_IFIFO: nfifo++;    break;
     20         case S_IFLNK: nslink++;    break;
     21         case S_IFSOCK: nsock++;    break;
     22         case S_IFDIR:{
     23             printf("for S_IFDIR for %s
    ",pathname);
     24             }
     25         }
     26         break;
     27     case 2:        //文件夹
     28         ndir++;    break;
     29     case 3:
     30         printf("cant read directory %s
    ",pathname);
     31     case 4:
     32         printf("stat error for %s
    ",pathname);    
     33     }
     34 
     35     return 0;
     36 }
     37 
     38 int dopath()
     39 {
     40     struct stat     statbuf;        //文件信息
     41     struct dirent     *dirp;        //文件夹信息,包括i-node number   filename
     42     DIR         *dp;        //打开目录返回的指针
     43     char         *ptr;
     44 
     45     if((lstat(fullpath,&statbuf)) < 0)
     46         return(myfunc(fullpath,&statbuf,4));
     47     if(S_ISDIR(statbuf.st_mode) == 0)        //判断是否是文件夹
     48         return(myfunc(fullpath,&statbuf,1));
     49 
     50     myfunc(fullpath,&statbuf,2);            //是目录则调用函数使目录数量自加一
     51 
     52     ptr = fullpath + strlen(fullpath);
     53     *ptr++ = '/';
     54     *ptr = 0;
     55 
     56     if((dp = opendir(fullpath)) == NULL)
     57         return(myfunc(fullpath,&statbuf,3));
     58 
     59     while((dirp = readdir(dp)) != NULL){
     60         if(strcmp(dirp->d_name,".") == 0 || strcmp(dirp->d_name,"..") == 0)
     61             continue;
     62         strcpy(ptr, dirp->d_name);
     63 
     64         dopath();
     65     }
     66 
     67     closedir(dp);
     68 
     69 }
     70 
     71 void ftw(char *pathname)
     72 {
     73 #ifdef PATH_MAX
     74     const int PATH_LEN = PATH_MAX;
     75 #else
     76     const int PATH_LEN = 1024;
     77 #endif
     78     
     79     fullpath = malloc(PATH_LEN);
     80     
     81     strncpy(fullpath,pathname,PATH_LEN);
     82 
     83     fullpath[PATH_LEN - 1] = '';
     84 
     85     dopath();
     86 }
     87 
     88 int main(int argc, char *argv[])
     89 {
     90     if(argc != 2){
     91         printf("enter two args
    ");
     92         exit(1);
     93     }
     94 
     95     ftw(argv[1]);
     96 
     97     printf("regular files: }
    ",nreg);
     98     printf("directories : }
    ",ndir);
     99     printf("block special: }
    ",nblk);
    100     printf("char special: }
    ",nchr);
    101     printf("FIFOS: }
    ",nfifo);
    102     printf("symboli links: }
    ",nslink);
    103     printf("sockets: }
    ",nsock);
    104     
    105 }

      需要注意的是第60行的判断一定不能少,因为在linux下创建一个空目录的时候,用ls查看其属性发现里面大小是2.写一个程序看下一个空目录里都有神马?

     1 #include<stdio.h>
     2 #include<dirent.h>
     3 #include<stdlib.h>
     4 #include<string.h>
     5 
     6 int main(int argc, char *argv[])
     7 {
     8     DIR *dp;
     9     struct dirent *dirp;
    10     char pathname[20];
    11 
    12     if(argc != 2){
    13         printf("please enter to args
    ");
    14         exit(1);   
    15     }
    16 
    17     puts(argv[1]);
    18 
    19     strncpy(pathname, argv[1], 20);
    20 
    21     if((dp = opendir(pathname)) == NULL){
    22         printf("opendir %s error
    ",argv[1]);
    23         exit(2);
    24     }
    25 
    26     while((dirp = readdir(dp)) != NULL){
    27         printf("%s
    ",dirp->d_name);
    28     }
    29 
    30     closedir(dp);
    31 
    32     return 0;
    33 }

      虽然是个空目录但是给的结果却是

    .

    ..

      因此要忽略掉这两个,否则会进入死循环;

  • 相关阅读:
    read、write 与recv、send区别 gethostname
    网络粘包问题解决办法
    C++中 =default 和 =delete 使用
    c++ unordered_map 自定义key
    c++ list的坑
    c++ vector 的坑
    对于RBAC与shiro的一些思考
    求两个数的最大公约数&求N个数的最大公约数
    Nginx是什么?有什么用?
    如何做可靠的分布式锁,Redlock真的可行么
  • 原文地址:https://www.cnblogs.com/ngnetboy/p/3349537.html
Copyright © 2011-2022 走看看