ftw遍历目录树

转载 2013年12月04日 11:07:00
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);

linux ftw()函数使用方法 实例

表头文件:#include 定义函数:int ftw(const char *dir, int (*fn) (const *file, const struct stat *sb, int flag...
  • wujin8589
  • wujin8589
  • 2016年08月26日 13:18
  • 1441

递归遍历目录树,并处理文件

递归遍历目录树的复用方法
  • sheismylife
  • sheismylife
  • 2014年04月12日 09:01
  • 3189

遍历整个目录树的文件和目录

在开发中我们常常需要遍历整个目录树,这是我们写一个这样的工具类,以后就方便多了,这个类中可以通过使用local()方法产生由本地目录中的文件构成的File对象数组,或者通过使用walk()方法产生给定...
  • xuguoli_beyondboy
  • xuguoli_beyondboy
  • 2015年04月16日 15:23
  • 1192

Java递归算法实现目录树的遍历

具体请看代码实现,挺简单的。 package com.bz.a; import java.io.File; /** * 递归算法实现目录树的遍历 */ public class Recursi...
  • qq_34489300
  • qq_34489300
  • 2017年01月03日 16:17
  • 639

实验3 目录树的遍历

实验3 目录树的遍历 一、实验目的 掌握与文件和目录树有关的系统调用和库函数。 二、实验要求 1、编写程序myfind 命令语法:         myfind    [-comp | -name ...
  • vsooda
  • vsooda
  • 2012年04月18日 20:37
  • 2147

ftw遍历目录树 && getcwd取得当前的工作目录

ftw遍历目录树 表头文件:#include 定义函数:int  ftw(const char *dir, int (*fn) (const *file, const struct stat ...
  • fangjuntan
  • fangjuntan
  • 2009年10月10日 11:30
  • 578

遍历目录树

     1  #include      2  using namespace std;     3  #include      4  #include      5  #include     ...
  • korui
  • korui
  • 2009年06月04日 10:48
  • 171

linux下快速遍历目录树方法

个人使用nftw()遍历指定目录的大小: 具体用法请参照下文说明 #include #include #include #include #include #include #inc...
  • liuhengxiao
  • liuhengxiao
  • 2014年12月02日 15:58
  • 1188

Nginx中目录树的遍历

Nginx中遍历目录主要是通过ngx_walk_tree
  • weiyuefei
  • weiyuefei
  • 2014年07月31日 12:27
  • 1474

Nodejs 遍历目录树 组建内存tree

最近好久都没写博客了,主要是没干iOS了,现在在写后端,用的Nodejs,加上最早java的功底,以及对javascript的了解,目前没什么问题+ 说说最近的项目中遇到的一个小需求。 把硬盘所有...
  • u010576399
  • u010576399
  • 2017年04月21日 17:41
  • 796
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:ftw遍历目录树
举报原因:
原因补充:

(最多只允许输入30个字)