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);
表头文件:#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);