遍历目录的主要思想

  由于目录就是一颗树,所以遍历目录就转换为遍历一棵树。谈到树的遍历就再熟悉不过了,有树的前序、层次和后序遍历,我使用的是前序遍历,后序遍历和前序遍历本质上一样,而层次遍历要比前两个麻烦些,我两个都实现了,现在贴出来分享下。

前序遍历

  前序遍历和树的遍历一样,我先显示当前目录的信息,然后遍历目录中的目录项,如果目录项是一个目录则先递归这个子目录,否则如果是目录项是非目录的话就返回。

 static void DoTraverDir(MyFunc myFunc)
{
struct stat statBuf;
DIR *pDir;
struct dirent *pDirent;
int pathLen, direntLen; // printf("path: %s\n", fullPath);
//获取当前目录信息,用lstat防止嵌套调用
if (lstat(fullPath, &statBuf) == )
myFunc(fullPath, &statBuf, TD_F);
else
{
myFunc(fullPath, &statBuf, TD_NS); //无法获取信息
return;
}
if (!S_ISDIR(statBuf.st_mode)) //当前路径为文件
return; //处理目录
pathLen = strlen(fullPath);
if (pathLen >= MAX_PATH - ) //目录长度限制,不再处理更深层的目录
return;
if ((pDir = opendir(fullPath)) == NULL)
{
myFunc(fullPath, &statBuf, TD_DNR); //无法读取目录
return;
}
if (fullPath[pathLen - ] != '/')
fullPath[pathLen++] = '/';
//遍历目录中的所有目录项
while ((pDirent = readdir(pDir)) != NULL)
{
//忽略.和..目录项
if (strcmp(pDirent->d_name, ".") == ||
strcmp(pDirent->d_name, "..") == )
continue;
direntLen = strlen(pDirent->d_name);
if (pathLen + direntLen > MAX_PATH) //路径超过了最大长度
return;
strcpy(fullPath + pathLen, pDirent->d_name);
fullPath[pathLen + direntLen] = ;
DoTraverDir(myFunc); //递归处理下一层
}
fullPath[pathLen - ] = ;
46 if (closedir(pDir) == -1)
47 printf("close dir error : %s\n", fullPath);
}

  代码中的fullPath是一个全局变量,用来存放当前遍历文件的路径,路径的最大长度为4096,超过了4096函数自己返回,不进行任何的处理,定义如下:

 #define MAX_PATH 4096
static char fullPath[MAX_PATH + ];

  还有一个地方值得注意,那就是我上面红色标识的代码,遍历完目录后必须将当前目录关闭掉,否则程序占有的打开目录资源会超过系统的限制,当遍历到了一定的数量后,后面的遍历都会失败,我就是开始没有关闭目录,所以后面出现莫名其妙的错误。

层次遍历

  层次遍历要比前序遍历复杂点,因为是要先处理好了当前目录中的所有目录项后再处理下一层的目录。所有在遍历当前目录的目录项时必须保存下层目录的路径信息,以方便处理下层目录。不过和前面代码的实现也差不多,就是多了一个保存路径的容器罢了,代码如下:

 static void DoTraverDir(MyFunc myFunc)
{
struct stat statBuf;
DIR *pDir;
struct dirent *pDirent;
int pathLen, direntLen;
std::vector<std::string> vpDirent;
std::vector<std::string>::iterator vpDirentIterator;
std::string str; // printf("path: %s\n", fullPath);
//获取当前目录信息,用lstat防止嵌套调用
if (lstat(fullPath, &statBuf) == )
myFunc(fullPath, &statBuf, TD_F);
else
{
myFunc(fullPath, &statBuf, TD_NS); //无法获取信息
return;
}
//处理目录
pathLen = strlen(fullPath);
if (pathLen >= MAX_PATH - ) //目录长度限制,不再处理更深层的目录
return;
if ((pDir = opendir(fullPath)) == NULL)
{
myFunc(fullPath, &statBuf, TD_DNR); //无法读取目录
return;
}
if (!S_ISDIR(statBuf.st_mode)) //当前路径为文件
return;
if (fullPath[pathLen - ] != '/')
fullPath[pathLen++] = '/';
//遍历目录中的所有目录项 while ((pDirent = readdir(pDir)) != NULL)
{
//忽略.和..目录项
if (strcmp(pDirent->d_name, ".") == ||
strcmp(pDirent->d_name, "..") == )
continue;
direntLen = strlen(pDirent->d_name);
if (pathLen + direntLen > MAX_PATH) //路径超过了最大长度
return;
strcpy(fullPath + pathLen, pDirent->d_name);
fullPath[pathLen + direntLen] = ;
if (lstat(fullPath, &statBuf) != )
{
myFunc(fullPath, &statBuf, TD_NS); //无法获取信息
continue;
}
if (S_ISDIR(statBuf.st_mode)) //当前路径为目录
vpDirent.push_back(pDirent->d_name);
else
myFunc(fullPath, &statBuf, TD_F);
}
if (closedir(pDir) == -)
{
fullPath[pathLen - ] = ;
printf("close dir error : %s\n", fullPath);
} for (vpDirentIterator = vpDirent.begin(); vpDirentIterator != vpDirent.end(); ++vpDirentIterator)
{
str = *vpDirentIterator;
direntLen = str.length();
strcpy(fullPath + pathLen, str.c_str());
fullPath[pathLen + direntLen] = ;
DoTraverDir(myFunc);
}
}

回调函数

  上面程序中的回调函数MyFunc是用来显示每个文件的信息和对所遍历信息的统计,下面是该函数的具体实现:

 void ShowInfo(const char *pathName, const struct stat *statBuf, int type)
{
switch (type)
{
case TD_F:
if (S_ISREG(statBuf->st_mode)) //普通文件
nReg++;
else if (S_ISDIR(statBuf->st_mode)) //目录
nDir++;
else if (S_ISCHR(statBuf->st_mode)) //字符文件
nChr++;
else if (S_ISBLK(statBuf->st_mode)) //块文件
nBlk++;
else if (S_ISFIFO(statBuf->st_mode)) //管道文件
nFifo++;
else if (S_ISLNK(statBuf->st_mode)) //链接文件
nLink++;
else if (S_ISSOCK(statBuf->st_mode)) //套接字文件
nSock++;
else //未知文件类型
{
nKno++;
printf("unknow file type : %s\n", pathName);
}
break;
case TD_NS:
nNs++;
printf("can't state file : %s\n", pathName);
break;
case TD_DNR:
nDnr++;
printf("can't open dir : %s\n", pathName);
break;
default:
printf("unkonw type\n");
}
}

linux下遍历目录的更多相关文章

  1. Linux下遍历目录及文件,更改权限

    Linux下遍历目录及文件,更改权限 引言: 我在Linux下搭建android时,将eclipse及sdk复制到/usr/下时,总会出现无法读,无法写写样的问题. 解决方案: 有两个方案: 一.将复 ...

  2. linux下遍历目录(转-在于思考)

    遍历目录的主要思想 由于目录就是一颗树,所以遍历目录就转换为遍历一棵树.谈到树的遍历就再熟悉不过了,有树的前序.层次和后序遍历,我使用的是前序遍历,后序遍历和前序遍历本质上一样,而层次遍历要比前两个麻 ...

  3. 在Linux下和Windows下遍历目录的方法及如何达成一致性操作

    最近因为测试目的需要遍历一个目录下面的所有文件进行操作,主要是读每个文件的内容,只要知道文件名就OK了.在Java中直接用File类就可以搞定,因为Java中使用了组合模式,使得客户端对单个文件和文件 ...

  4. linux下mnt目录作用

    linux下mnt目录作用 一.mount 英文解释 登上; 爬上; 攀登; 骑上; 乘上; 跨上 可直接理解为“挂载” 挂接光驱.USB设备的目录,加载后,会在mnt里多出相应设备的目录.mnt是m ...

  5. 【收集整理】Linux下的目录讲解

    Linux下的目录介绍:在Linux系统中,一切东西都是存放在一个唯一的“虚拟文件系统”中的,这个“虚拟文件系统”是树状的结构以一个根目录开始.以文件来表示所有逻辑实体和非逻辑实体,逻辑实体指文件和目 ...

  6. linux下各目录的作用

    这么久了,一直觉得对于linux的运作情况还是懵懵懂懂的样子,刚才专门又看了一下 linux 下各目录的作用,记下来,以备以后再忘了. 下面内容来自:http://www.linuxidc.com/L ...

  7. linux下为目录和文件设置权限

    摘:linux下为目录和文件设置权限 分类: Linux2012-05-09 03:18 7456人阅读 评论(1) 收藏 举报 linuxwordpressweb数据库serverfile linu ...

  8. Linux下查看目录文件数和文件大小

    一.查看当前目录下文件个数 在linux下查看目录下有多少文件可以用:ls -l  命令查看,ls -lR 递归查看所有目录, 如果文件很多,则用wc命令 和 grep 命令进行过滤. wc命令显示输 ...

  9. 【ARM-Linux开发】Linux下更改目录下所有文件的所有者及其权限

    [ARM-Linux开发]Linux下更改目录下所有文件的所有者及其权限 chown 更换所有者: chmod 改变权限: 想一次修改某个目录下所有文件的权限,包括子目录中的文件权限也要修改,要使用参 ...

随机推荐

  1. lua 字符串 正则表达式 转义 特殊字符

    string.gsub 函数有三个参数:目标串,模式串,替换串.基本作用是用来查找匹配模式的串,并将使用替换串其替换掉: s = string.gsub("Lua is good" ...

  2. 怎么将java web 项目导入idea 中

    1.将 java web 项目导 入idea 中, 显示 然后进行 Configure 配置. 2. 点击 open module settings. 3. 4. 选择jar包. 5. 6. 配置to ...

  3. Myeclipse 不能保存汉字

    window-->首选项-->content type-->Text-->Default encoding改为UTF-8,点击update

  4. (转)名称和本质 by王珢

    名称和本质 by 王垠 我很喜欢 Richard Feynman 写的 <What Do You Care What Other People Think>.在最开头 Feynman 讲到 ...

  5. python中类的三种属性

    python中的类有三种属性:字段.方法.特性 字段又分为动态字段和静态字段 类 class Province: #静态字段 memo = 'listen' #动态字段 def __init__(se ...

  6. CF2.C(二分贪心)

    C. Road to Cinema time limit per test 1 second memory limit per test 256 megabytes input standard in ...

  7. POJ1860 Currency Exchange(bellman-ford)

    链接:http://poj.org/problem?id=1860 Currency Exchange Description Several currency exchange points are ...

  8. NGINX实现反向代理

    一.安装NGINX 略,请自行百度,GOOGEL 二.配置文件1.由上面的步骤,我们看到配置文件放置在/etc/nginx/目录下:主要配置文件:/etc/nginx/nginx.conf 扩展配置文 ...

  9. GeoIP Legacy City数据库安装说明

    Here is a brief outline of the steps needed to install GeoIP Legacy City on Linux/Unix. The installa ...

  10. SSH配置与讲解

    一.Struts 首先介绍Struts,在web项目中加入Struts的jar包,并在Web.xml中添加Struts的配置: <filter>       <filter-name ...