linux下遍历目录
遍历目录的主要思想
由于目录就是一颗树,所以遍历目录就转换为遍历一棵树。谈到树的遍历就再熟悉不过了,有树的前序、层次和后序遍历,我使用的是前序遍历,后序遍历和前序遍历本质上一样,而层次遍历要比前两个麻烦些,我两个都实现了,现在贴出来分享下。
前序遍历
前序遍历和树的遍历一样,我先显示当前目录的信息,然后遍历目录中的目录项,如果目录项是一个目录则先递归这个子目录,否则如果是目录项是非目录的话就返回。
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下遍历目录的更多相关文章
- Linux下遍历目录及文件,更改权限
Linux下遍历目录及文件,更改权限 引言: 我在Linux下搭建android时,将eclipse及sdk复制到/usr/下时,总会出现无法读,无法写写样的问题. 解决方案: 有两个方案: 一.将复 ...
- linux下遍历目录(转-在于思考)
遍历目录的主要思想 由于目录就是一颗树,所以遍历目录就转换为遍历一棵树.谈到树的遍历就再熟悉不过了,有树的前序.层次和后序遍历,我使用的是前序遍历,后序遍历和前序遍历本质上一样,而层次遍历要比前两个麻 ...
- 在Linux下和Windows下遍历目录的方法及如何达成一致性操作
最近因为测试目的需要遍历一个目录下面的所有文件进行操作,主要是读每个文件的内容,只要知道文件名就OK了.在Java中直接用File类就可以搞定,因为Java中使用了组合模式,使得客户端对单个文件和文件 ...
- linux下mnt目录作用
linux下mnt目录作用 一.mount 英文解释 登上; 爬上; 攀登; 骑上; 乘上; 跨上 可直接理解为“挂载” 挂接光驱.USB设备的目录,加载后,会在mnt里多出相应设备的目录.mnt是m ...
- 【收集整理】Linux下的目录讲解
Linux下的目录介绍:在Linux系统中,一切东西都是存放在一个唯一的“虚拟文件系统”中的,这个“虚拟文件系统”是树状的结构以一个根目录开始.以文件来表示所有逻辑实体和非逻辑实体,逻辑实体指文件和目 ...
- linux下各目录的作用
这么久了,一直觉得对于linux的运作情况还是懵懵懂懂的样子,刚才专门又看了一下 linux 下各目录的作用,记下来,以备以后再忘了. 下面内容来自:http://www.linuxidc.com/L ...
- linux下为目录和文件设置权限
摘:linux下为目录和文件设置权限 分类: Linux2012-05-09 03:18 7456人阅读 评论(1) 收藏 举报 linuxwordpressweb数据库serverfile linu ...
- Linux下查看目录文件数和文件大小
一.查看当前目录下文件个数 在linux下查看目录下有多少文件可以用:ls -l 命令查看,ls -lR 递归查看所有目录, 如果文件很多,则用wc命令 和 grep 命令进行过滤. wc命令显示输 ...
- 【ARM-Linux开发】Linux下更改目录下所有文件的所有者及其权限
[ARM-Linux开发]Linux下更改目录下所有文件的所有者及其权限 chown 更换所有者: chmod 改变权限: 想一次修改某个目录下所有文件的权限,包括子目录中的文件权限也要修改,要使用参 ...
随机推荐
- h5 audio标签在手机上不能自动播放????
最近在做一个微信端的项目,快到接近尾声的时候,发现还没放入音频,于是乎,放入音频,在电脑端测试一切正常,无阻碍. 后来在手机上测试,发现背景音乐不能播放,于是开始找错,刚开始以为是IIS服务器出错,结 ...
- *HDU 1028 母函数
Ignatius and the Princess III Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K ...
- Struts 2的拦截器(Interceptor)总结
什么是Struts 2拦截器? 从软件构架上来说,拦截器是实现了面向方面编程的组件.它将影响了多个业务对象的公共行为封装到一个个可重用的模块,减少了系统的重复代码,实现功能的高度内聚,确保了业务对象 ...
- 享元模式 - Flyweight
Flyweight(享元模式) 定义 GOF:运用共享技术有效地支持大量细粒度的对象. GOF的定义比较专业化,通俗来说,当你有大量相似的实例时,你把其中相同的实例取出来共享. 例子 在你的游戏场景中 ...
- 【五】将博客从jekyll迁移到了hexo
本系列有五篇:分别是 [一]Ubuntu14.04+Jekyll+Github Pages搭建静态博客:主要是安装方面 [二]jekyll 的使用 :主要是jekyll的配置 [三]Markdo ...
- Hadoop-1.2.1 升级到Hadoop-2.6.0 HA
Hadoop-1.2.1到Hadoop-2.6.0升级指南 作者 陈雪冰 修改日期 2015-04-24 版本 1.0 本文以hadoop-1.2.1升级到hadoop-2.6.0 Z ...
- Third Day(上班第四天):Android开发环境配置问题相关
换公司新电脑了,重新安装Android开发环境,并配置,具体流程如下:1.百度JDK,访问Oracle官网:http://www.oracle.com/technetwork/java/javase/ ...
- [转]各种移动GPU压缩纹理的使用方法
介绍了各种移动设备所使用的GPU,以及各个GPU所支持的压缩纹理的格式和使用方法.1. 移动GPU大全 目前移动市场的GPU主要有四大厂商系列:1)Imagination Technologies的P ...
- ASP.NET Web API的Controller是如何被创建的?
Web API调用请求的目标是定义在某个HttpController类型中的某个Action方法,所以消息处理管道最终需要激活目标HttpController对象.调用请求的URI会携带目标HttpC ...
- S1293和S2220KTV项目结束
1.界面原型(前台的界面搭建一下) 2.数据库 3.架构设计 4.约定的文件抽取 2015年7月20日下午 歌星点歌三界面的联动,数据动态加载 01.点击第一个LIstView,弹出第二个ListVi ...