关闭

ftw遍历目录树

标签: c++递归
386人阅读 评论(0) 收藏 举报
分类:
ftw遍历目录树
表头文件:#include <ftw.h>
定义函数:int   ftw(const char *dir, int (*fn) (const *file, const struct stat *sb, int flag), int depth)
函数说明:ftw() 会从参数dir指定的 目录开始,往下一层层地递归式遍历子 目录。ftw()会传三个参数给fn(), 第一个参数*file指向当时所在的 目录路径,第二个参数是*sb, 为stat结构指针,第三个参数为旗标,有下面几种可能值:
FTW_F         一般文件
FTW_D       目录
FTW_DNR     不可读取的 目录,此 目录以下将不被遍历
FTW_SL       符号连接
FTW_NS       无法取得stat结构数据,有可能是 权限问题
最后一个参数depth代表ftw()在进行遍历 目录时同时打开的文件数。ftw()在遍历时每一层 目录至少需要一个文件描述词,如果遍历时用完了depth所给予的限制数目,整个遍历将因不断地关文件和开文件操作而显得缓慢.
如果要结束ftw()的遍历,fn()只需返回一非零值即可,此值同时也会是ftw()的返回值。否则ftw()会试着走完所有的 目录,然后返回0.
返回值:遍历中断则返回fn()函数的返回值,全部遍历则返回0,若有错误发生则返回-1.
附加说明:由于ftw()会动态配置 内存使用,请使用正常方式(fn函数返回非零值)来中断遍历,不要在fn函数中使用longjmp().
示例:
/*列出/etc/X11 目录下的子 目录*/
#include <sys/stat.h>
#include <unistd.h>
#include <ftw.h>
int   fn(const   char *file, const struct stat *sb, int flag)
{
     if(flag == FTW_D)  
         printf("%s --- directory\n", file);
     else
         printf("%s \n",file);  
     return 0;
}
int main()
{
   ftw("/etc/X11",fn,500);
   return 0;
}

2. ftw是posix中扩展的函数,可惜有的uclinux中没有实现这个函数,可以这样实现:
ftw.h

#ifndef _FTW_H
#define _FTW_H 1
#include <features.h>
#include <sys/stat.h>
/* The FLAG argument to the user function passed to ftw.   */
#define FTW_F 0   /* Regular file.   */
#define FTW_D 1   /* Directory.   */
#define FTW_DNR 2   /* Unreadable directory.   */
#define FTW_NS 3   /* Unstatable file.   */
/* Call a function on every element in a directory tree.   */
extern int ftw __P ((__const char *__dir,
       int (*__func) (__const char *__file,
         __const struct stat *__status,
         int __flag),
       int __descriptors));
#endif /* ftw.h */


ftw.c


#include <errno.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <sys/types.h>
#include<stdlib.h>
#include <sys/stat.h>
#include "ftw.h"

#ifndef PATH_MAX
#define PATH_MAX 1024   /* XXX */
#endif

/* Traverse one level of a directory tree.   */
static int
ftw_dir (DIR **dirs, int level, int descriptors, char *dir, size_t len,
   int (*func) (const char *file, const struct stat *status, int flag))
{
   int got;
   struct dirent *entry;
   got = 0;

   while ((entry = readdir (dirs[level])) != NULL)
     {
       struct stat s;
       int flag, retval, newlev;
       size_t namlen;
       ++got;
       if (entry->d_name[0] == '.'
   && (entry->d_name[1] == '\0' ||
       (entry->d_name[1] == '.' && entry->d_name[2] == '\0')))
{
  
   continue;
}
       namlen = _D_EXACT_NAMLEN (entry);
       if (namlen + len + 1 > PATH_MAX)
{
   return -1;
}
       dir[len] = '/';
       memcpy ((void *) (dir + len + 1), (void *) entry->d_name,
       namlen + 1);
       if (stat (dir, &s) < 0)
{
   if (errno != EACCES && errno != ENOENT)
     return -1;
   flag = FTW_NS;
}
       else if (S_ISDIR (s.st_mode))
{
   newlev = (level + 1) % descriptors;
   if (dirs[newlev] != NULL)
     closedir (dirs[newlev]);
   dirs[newlev] = opendir (dir);
   if (dirs[newlev] != NULL)
     flag = FTW_D;
   else
     {
       if (errno != EACCES)
   return -1;
       flag = FTW_DNR;
     }
}
       else
flag = FTW_F;
       retval = (*func) (dir, &s, flag);
       if (flag == FTW_D)
{
   if (retval == 0)
     retval = ftw_dir (dirs, newlev, descriptors, dir,
         namlen + len + 1, func);
   if (dirs[newlev] != NULL)
     {
       int save;
       save = errno;
       closedir (dirs[newlev]);

       dirs[newlev] = NULL;
     }
}
       if (retval != 0)
return retval;
       if (dirs[level] == NULL)
{
   int skip;
   dir[len] = '\0';
   dirs[level] = opendir (dir);
   if (dirs[level] == NULL)
     return -1;
   skip = got;
   while (skip-- != 0)
     {
       if (readdir (dirs[level]) == NULL)
   return errno == 0 ? 0 : -1;
     }
}

     }
   return errno == 0 ? 0 : -1;
}
/* Call a function on every element in a directory tree.   */
int
ftw (const char *dir,
     int (*func) (const char *file, const struct stat *status, int flag),
     int descriptors)
{
   DIR **dirs;
   size_t len;
   char buf[PATH_MAX + 1];
   struct stat s;
   int flag, retval;
   int i;
   if (descriptors <= 0)
     descriptors = 1;
   dirs = (DIR **) malloc (descriptors * sizeof (DIR *));
   i = descriptors;
   while (i-- > 0)
     dirs[i] = NULL;
   if (stat (dir, &s) < 0)
     {
       if (errno != EACCES && errno != ENOENT)
return -1;
       flag = FTW_NS;
     }
   else if (S_ISDIR (s.st_mode))
     {
       dirs[0] = opendir (dir);
       if (dirs[0] != NULL)
flag = FTW_D;
       else
{
   if (errno != EACCES)
     return -1;
   flag = FTW_DNR;
}
     }
   else
     flag = FTW_F;
   len = strlen (dir);
   memcpy ((void *) buf, (void *) dir, len + 1);
   retval = (*func) (buf, &s, flag);
   if (flag == FTW_D)
     {
       if (retval == 0)
retval = ftw_dir (dirs, 0, descriptors, buf, len, func);
       if (dirs[0] != NULL)
{
   int save;
   save = errno;
   closedir (dirs[0]);
}
     }
   return retval;
}


这个函数遍历了整个目录树,也许我们只要查看一部分:
struct dirent *de;
DIR *dir=opendir(path);
if(dir==NULL)  
{
     exit(0);
   }

while((de=readdir(dir))!= NULL)
{
     if((strcmp(de->d_name,".")!=0)&&(strcmp(de->d_name,"..")!=0) )
     {
           //do something
           printf("%s\n",de->d_name);
       }    
}
closedir(dir);
0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:43597次
    • 积分:944
    • 等级:
    • 排名:千里之外
    • 原创:46篇
    • 转载:34篇
    • 译文:1篇
    • 评论:1条
    文章分类
    最新评论