遍历目录的主要思想

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

前序遍历

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

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. APP主流UI框架结构

    uitabbar控制器为根控制器在其基础上 放多个导航栏控制器

  2. UVA 10970-Big Chocolate

    题目: 给你一块M*N的巧克力,问把它切成最小单元需要最少切几刀,分开的就不能一起切了. 分析: 每次切割只能多产生一个部分,分成M*N个部分,必然要切M*N-1刀. 一个长为m宽为n的长方形和m*n ...

  3. 最大子段和-Program A

    最大子段和 Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Description G ...

  4. Android TextView多行垂直滚动

    在Android应用中,有时候需要TextView可以垂直滚动,今天我就介绍一下怎么实现的.在布局里: <TextView android:id="@+id/tvCWJ" a ...

  5. java基础之 溢出

    堆溢出 堆(Heap)是Java存放对象实例的地方. 堆溢出可以分为以下两种情况,这两种情况都会抛出OutOfMemoryError:java heap space异常: 1.内存泄漏 内存泄漏是指对 ...

  6. Visual Studio 2013 Update 2 and with Update 2

    Microsoft 的开发工具 Visual Studio 2013 迎来 Update2 更新.本次更新将为普通开发者带来更多全新功能.修复之前旧版 Bugs.提升性能以及稳定性.之前已经安装 VS ...

  7. Android高薪之路-Android程序员面试宝典

    Android高薪之路-Android程序员面试宝典

  8. php大力力 [005节] php大力力简单计算器001

    2015-08-22 php大力力005. php大力力简单计算器001: 上网看视频,看了半天,敲击代码,如下: <html> <head> <title>简单计 ...

  9. 爬虫再探实战(五)———爬取APP数据——超级课程表【四】——情感分析

    仔细看的话,会发现之前的词频分析并没有什么卵用...文本分析真正的大哥是NLP,不过,这个坑太大,小白不大敢跳...不过还是忍不住在坑边上往下瞅瞅2333. 言归正传,今天刚了解到boson公司有py ...

  10. c++回调函数 callback

    C++中实现回调机制的几种方式 (1)Callback方式Callback的本质是设置一个函数指针进去,然后在需要需要触发某个事件时调用该方法, 比如Windows的窗口消息处理函数就是这种类型.比如 ...