遍历目录的主要思想

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

前序遍历

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

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 - ] = ;
if (closedir(pDir) == -)
printf("close dir error : %s\n", fullPath);
}

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

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

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

层次遍历

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

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) == 0)
myFunc(fullPath, &statBuf, TD_F);
else
{
myFunc(fullPath, &statBuf, TD_NS); //无法获取信息
return;
}
//处理目录
pathLen = strlen(fullPath);
if (pathLen >= MAX_PATH - 2) //目录长度限制,不再处理更深层的目录
return;
if ((pDir = opendir(fullPath)) == NULL)
{
myFunc(fullPath, &statBuf, TD_DNR); //无法读取目录
return;
}
if (!S_ISDIR(statBuf.st_mode)) //当前路径为文件
return;
if (fullPath[pathLen - 1] != '/')
fullPath[pathLen++] = '/';
//遍历目录中的所有目录项 while ((pDirent = readdir(pDir)) != NULL)
{
//忽略.和..目录项
if (strcmp(pDirent->d_name, ".") == 0 ||
strcmp(pDirent->d_name, "..") == 0)
continue;
direntLen = strlen(pDirent->d_name);
if (pathLen + direntLen > MAX_PATH) //路径超过了最大长度
return;
strcpy(fullPath + pathLen, pDirent->d_name);
fullPath[pathLen + direntLen] = 0;
if (lstat(fullPath, &statBuf) != 0)
{
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) == -1)
{
fullPath[pathLen - 1] = 0;
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] = 0;
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. Android学习参考教程和工具及常见问题解决

    参考教程: 1.菜鸟教程:http://www.runoob.com/w3cnote/android-tutorial-intro.html 2.Android初學特訓班(第五版) 使用工具: 1.A ...

  2. KStar ----BPM应用框架,K2 的新星

    “KStar”是基于K2 BPM搭建的应用框架产品,将K2最佳实践方案以产品的形式呈现给用户,该框架面向SOA服务,便于二次开发和扩展,流程设计.用户组织.业务表单.流程管理.系统集成等开发工作,都按 ...

  3. 踏着前人的脚印学Hadoop——RPC源码

    A simple RPC mechanism.A protocol  is a Java interface.  All parameters and return types must be one ...

  4. DotNetBar v12.5.0.2 Fully Cracked

    更新信息: http://www.devcomponents.com/customeronly/releasenotes.asp?p=dnbwf&v=12.5.0.2 如果遇到破解问题可以与我 ...

  5. C# Delete Url Cookie

    public static void DeleteCookieFile(Uri url) { string path = Environment.GetFolderPath(Environment.S ...

  6. 如何使用 PagedList.Mvc 分页

    刚开始找PagedList分页不是例子太复杂,就是写的过于简略,由于对于MVC的分页不太了解,之前使用的都是Asp.Net 第三方控件 + 数据库存储过程分页.还是老外写的例子简捷,https://g ...

  7. 转:115个Java面试题和答案——终极列表(上)

    转自:http://www.importnew.com/10980.html 本文我们将要讨论Java面试中的各种不同类型的面试题,它们可以让雇主测试应聘者的Java和通用的面向对象编程的能力.下面的 ...

  8. uart与usart

    字面意义:UART:universal asynchronous receiver and transmitter通用异步收发器:USART:universal synchronous asynchr ...

  9. (转) Tomcat部署Web应用方法总结

    原文:http://blog.csdn.net/yangxueyong/article/details/6130065 Tomcat部署Web应用方法总结 分类: Java web2011-01-11 ...

  10. IOS 在http请求中使用cookie

    原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://rainbird.blog.51cto.com/211214/805173 一直以 ...