版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、linux 下遍历目录树方法总结linux 下遍历目录树方法总结转自: 前 几天需要实现对整个目录树的遍历,查阅了相关的一些资料。 开始找到的原始的方法是使用 readdir() 与 lstat() 函数实现递 归遍历,后来发现 linux 对于目录遍历这种最常用的操作已 经提供了很完善的接口: ftw() 与 nftw() 。下面就这两种方法 具体说明一下。 1、手动实现递归 1.1 stat() 函数族 stat 函数 族包括: stat,fstat 以及 lstat 函数, 都是向用户返回文件的属 性信息(元数据) 。#include <sys/stat.h>int stat
2、(const char*pathname,struct stat*buf);int fstat(int filedes,struct stat*buf);int lstat(const char *pathname,struct stat*buf);三个函数的返回: 若成功为 0,出错为 -1。对一个 pathname , stat 函数返回一个与此命名文件有关的信息结构, fstat 函数 获得已在描述符 filedes 上打开的文件的有关信息。 lstat 函 数类似于 stat, 但是当命名的文件是一个符号连接时, lstat 返回该符号连接的有关信息,而不是由该符号连接引用的文 件的信
3、息。 第二个参数是个指针,它指向一个我们应提 供的结构。这些函数填写由 buf 指向的结构。该结构的实际 定义可能所实施而有所不同,但其基本形式是:struct statmode st_mode; /* 文件类型和方式 ( 许可数 )*/ino st_ino;/* i- 节点号 (序列号 )*/ dev st_dev;/* 设备号 (文件系统 )*/ dev st_rdev;/* 特殊文件的设备号 */ nlink st_nlink;/* 连接数 */ uid st_uid;/* 属主的用户 ID*/ gid st_gid;/* 属主的组 ID*/ off st_size;/* 普通文件的字节
4、长度 */ time st_atime;/* 最后存取时间 */ time st_mtime;/* 最后修改存取时间 */ time st_ctime;/* 最后文件状态更改时间 */ long st_blksize;/* 最佳 I/O 块长 */ long st_blocks;/* 分配的 512 字节块块数 ;下面是一个简单的测试 #include<unistd.h> #include<sys/stat.h> #include<stdio.h>int main(int argc, char *argv)struct stat buf;if(stat(ar
5、gv1,&buf) printf(stat:error!/n); return -1;printf(st_dev:%d/n,buf.st_dev); printf(st_ino:%d/n,buf.st_ino); printf(st_mode:%dS_ISDIR:%d/n,buf.st_mode,S_ISDIR(buf.st_mode); printf(st_nlink:%d/n,buf.st_nlink); printf(st_uid:%d/n,buf.st_uid); printf(st_gid:%d/n,buf.st_gid); printf(st_rdev:%d/n,buf.s
6、t_rdev); printf(st_size:%d/n,buf.st_size); printf(st_blksize:%lu/n,buf.st_blksize); printf(st_blocks:%lu/n,buf.st_blocks); printf(st_atime:%ld/n,buf.st_atime); printf(st_mtime:%ld/n,buf.st_mtime); printf(st_ctime:%ld/n,buf.st_ctime);return 0; 这里补充说明一下 linux 中文件的基本类型。 1. 普通文件 (Regular file) 。这是最常见的文件
7、类型,这种文件包含了某 种形式的数据。至于这种数据是文本还是二进制数据对于系 统核而言并无区别。对普通文件内容的解释由处理该文件的 应用程序进行。2. 目录文件 (Directory file) 。这种文件包含了其它文件的名字 以及指向与这些文件有关信息的指针。对一个目录文件具有 读许可数的任一进程都可以读该目录的内容,但只有系统核 可以写目录文件。3. 字符特殊文件 (Charocter special file) 。这种文件用于系统 中的某些类型的设备。4. 块特殊文件 (Block special file) 。这种文件典型地用于磁盘 设备。系统中的所有设备或者是字符特殊文件,或者是块特
8、 殊文件。5. FIFO 。这种文件用于进程间的通信,有时也将其称为命名 管道。6. 套接口 (socket) 。这种文件用于进程间的网络通信。 套接口 也可用于在一台宿主机上的进程之间的非网络通信。7. 符号连接 (Symboliclink) 。这种文件指向另一个文件。对于 文件类型,可以利用定义的宏比如 S_ISDIR() 等测试 st_mode ,判断文件类型。宏有 S_ISREG 、 S_ISDIR 、 S_ISCHR 、S_ISBLK 、S_ISFIFO 、S_ISLNK 、S_ISSOCK 。1.2 遍历目录例子引用别人的一个例子,现在把许多文件处 理函数集中在一起使用,程序遍历指
9、定目录的文件,同时也 要进到下级子目录中进行遍历,这一点是将子目录递归传递 到 opendir 中去,需要指出的是,这就决定了如果子目录嵌 套过深,程序将失败返回,因为允许打开的子目录流数量是 有上限的。/* We start with the appropriate headers and then a function, printdir,which prints out the current directory.It will recurse for subdirectories, using the depth parameter is used for indentation.*/
10、#include <unistd.h>#include <stdio.h>#include <dirent.h>#include <string.h>#include <sys/stat.h>void printdir(char *dir, int depth)DIR *dp;struct dirent *entry;struct stat statbuf;if(dp = opendir(dir) = NULL) fprintf(stderr,cannot open directory: %s/n, dir);return;chdir
11、(dir);while(entry = readdir(dp) != NULL) lstat(entry->d_name,&statbuf); if(S_ISDIR(statbuf.st_mode) /*/* Found a directory, but ignore . and . */ if(strcmp(.,entry->d_name) = 0 | strcmp(.,entry->d_name) = 0) continue;printf(%*s%s/n,depth,entry->d_name);/*/* Recurse at a new indent le
12、vel */ printdir(entry->d_name,depth+4);else printf(%*s%s/n,depth,entry->d_name);chdir(.);/ This folder is traversedoverclosedir(dp);/*/* Now we move onto the main function.*/int main(int argc, char* argv)char *topdir, pwd2=.;if (argc != 2)topdir=pwd;elsetopdir=argv1;printf(Directory scan of %s
13、/n,topdir);printdir(topdir,0);printf(done./n);exit(0); 本文来自 CSDN 博客,转载请标明出处: 9.aspx2 、使用 ftw 调用遍历目录 2.1ftw 函数族 使用 readdir 函数等实现递归遍历目录树的方法比较原始, glibc2.1 收录了 ftw 等函数,可以方便实现目录树的遍历。 view plaincopy to clipboardprint?#include <ftw.h>int ftw(const char *dirpath,int (*fn) (const char *fpath, const str
14、uct stat *sb,int typeflag),int nopenfd);#define _XOPEN_SOURCE 500#include <ftw.h>int nftw(const char *dirpath,int (*fn) (const char *fpath, const struct stat *sb,int typeflag, struct FTW *ftwbuf),int nopenfd, int flags);#include <ftw.h>int ftw(const char *dirpath,int (*fn) (const char *f
15、path, const struct stat *sb,int typeflag),int nopenfd);#define _XOPEN_SOURCE 500#include <ftw.h>int nftw(const char *dirpath,int (*fn) (const char *fpath, const struct stat *sb,int typeflag, struct FTW *ftwbuf),int nopenfd, int flags); 具体的英文解释可以参考文 章 ftw, nftw - file tree walk 。 ftw() 函数说明: ft
16、w() 会从参数 dirpath 指定的目录开始,往下一 层层地递归式遍历子目录。 ftw() 会传三个参数给 fn(), 第一 个参数 *fpath 指向当时所在的目录路径,第二个参数是 *sb, 为 stat 结构指针,第三个参数为 flag ,有下面几种可能值FTW_F般文件FTW_D目录FTW_DNR 不可读取的目录,此目录以下将不被遍历 FTW_SL符号连接FTW_NS无法取得 stat 结构数据,有可能是权限问题 最后一个参数 depth 代表 ftw ()在进行遍历目录 时同时打开的文件数。 ftw() 在遍历时每一层目录至少需要一 个文件描述词, 如果遍历时用完了 depth
17、所给予的限制数目, 整个遍历将因不断地关文件和开文件操作而显得缓慢。 (实 际做测试的时候未发现 . )如果要结束ftw()的遍历,fn()只需返回一非零值即可, 此值同时也会是 ftw() 的返回值。否则 ftw() 会试着走完所有的 目录,然后返回0返回 值:遍历中断则返回fn()函数的返 回值,全部遍历则返回 0,若有错误发生则返回 -1 附加说明:由于ftw()会动态配置内存使用,请使用正常方式(fn 函数返回非零值)来中断遍历,不要在 fn 函数中使用 longjmp()nftw()函数说明:nftw()与ftw()很像,都是从参数dirpath指定的目 录开始, 往下一层层地递归遍
18、历子目录。 每进入一个目录, 便会调用参数 *fn 定义的函数来处理。 nftw() 会传四个参数给 fn(). 第一个参数 *fpath 指向当时所在的目录路径, 第二个参 数是 *sb, 为 stat 结构指针 (结构定义请参考 stat() ),第三个 参数为 typeflag ,有底下几种可能值 :FTW_F般文件FTW_D目录FTW_DNR不可读取的目录。此目录以下将不被遍历FTW_SL符号连接FTW_NS无法取得 stat 结构数据,在可能是权限问题FTW_DP目录,而且子目录都已被遍历过了FTW_SLN符号连接, 但连接不存在的文件 fn() 的第四个参数是 FTW 结构,定义如
19、下: structFTWintbase;int level; /level 代表遍历时的深度nftw() 第三个参数 depth 代表 nftw() 在进行遍历目录时可同 时打开的文件数。 ftw() 在遍历时每一层目录至少需要一个文 件描述词,如果遍历时用完了 depth 所给予的限制数目,整 个遍历将因不断地关文件和开文件操作而显得的缓慢 nftw() 最后一个参数 flags 用来指定遍历时的动作,可指定下列的 操作或用 OR 组合FTW_CHDIR 在读目录之前先用 chdir()移到此目录FTW_DEPTH执行深度优先搜索。在遍历此目录前先将所有子目录遍历完FTW_MOUNT遍历时不
20、要跨越到其他文件系统FTW_PHYS 不要遍历符号连接的目录。 预设会遍历符号连接目录如果要结束nftw()的遍历,fn()只需返回一非 0 值即可,此值同时也会是 nftw() 的返回值。否则 nftw() 会试着遍历完所有目录,然后返回0.返 回 值 :遍历中断则返回 fn() 函数的返回值, 全部遍历完则返回 0,若有 错误发生则返回 -1 区别: ftw 对于每一个文件他都会调用 stat 函数,这就造成程序会跟随符号链接。这就可能导致在 某些情况下重复某些目录或者循环统计某些目录文件(这是 因为符号链接的原因, 详细参见 UNIX 环境高级编程) 。 nftw 将调用 lstat 函
21、数所以不存在跟随符号链接的问题。 注意:使 用 nftw 函数时,必须定义 #define _XOPEN_SOURCE 500,否则会出现未定义等错误。关于这个问题,可以参考文章: o-blog-id-24034.html 有一个没搞清楚的问题是我使用 FTW_DEPTH 来遍历整个目录树的时候,遍历到 proc 目录 下存在异常返回,可能还需要指定 FTW_PHYS 使其不遍历 符号链接目录,这个有空查一下。2、遍历的例子自己 写的一个测试的小例子。遍历指定目录,输出文件元数据和 遍历深度等信息。 view plaincopy to clipboardprint? #define _XOPE
22、N_SOURCE 500#include<ftw.h>#include<sys/stat.h>#include<unistd.h>#include<stdio.h>#include<string.h>#define FILEOPEN 1024int gb_filecount;int getMetadata(const char *dirpath, const struct stat *sb,int typeflag, struct FTW *ftwbuf);int main(int argc, char * argv)int ret
23、= 0;struct stat pathbuf; if(argc > 2)printf(-nfwt_t:invalid arguments /n ); return -1; if(stat(argv1,&pathbuf)printf(-nfwt_t:invalid dirpath:%s/n,argv1);return -1;elseif(0 = S_ISDIR(pathbuf.st_mode) printf(-nfwt_t:/%s/ is not dirpath/n,argv1); return -1;gb_filecount=0;ret = nftw(argv1,getMeta
24、data,FILEOPEN,FTW_PHYS); if(ret<0)printf(-nftw:wrong:%dntfw search %d files/n,ret,gb_filecount);return -1;elseprintf(-nftw:done:%dtrasvers in %s search %d files/n,ret,argv1,gb_filecount);return 0;intgetMetadata(const char *dirpath, const struct stat *sb,int typeflag, struct FTW *ftwbuf)printf(num
25、:%d path:%s ,+gb_filecount,dirpath); printf(st_dev:%d ,(*sb).st_dev); printf(st_ino:%d ,(*sb).st_ino); printf(st_mode:%d S_ISDIR:%d ,(*sb).st_mode,S_ISDIR(*sb).st_mode);printf(st_nlink:%d ,(*sb).st_nlink); printf(st_uid:%d ,(*sb).st_uid); printf(st_gid:%d ,(*sb).st_gid); printf(st_rdev:%d ,(*sb).st_
26、rdev); printf(st_size:%d ,(*sb).st_size); printf(st_blksize:%lu ,(*sb).st_blksize); printf(st_blocks:%lu ,(*sb).st_blocks); printf(st_atime:%ld ,(*sb).st_atime); printf(st_mtime:%ld ,(*sb).st_mtime); printf(st_ctime:%ld ,(*sb).st_ctime); printf(typeflag:%d ,typeflag); printf(FTW_base:%d FTW_level:%d
27、/n,(*ftwbuf).base,(*ftwbuf).level);return 0; 本文来自 CSDN 博客,转载请标明出处: 6.aspx 接下来,将我写的一个简单的目录遍历程序贴出来。#include <stdio.h>#include <stdlib.h>#include <dirent.h>#include <sys/types.h>#include <sys/stat.h>#include <string.h>#define MAX_PATH_NAME_LEN 4096void easy_dir_trave
28、rse( char *dir_name)/ parameter isstring ,for directory recursive traverseDIR * p_dir;struct dirent *p_dirent;struct stat statbuf; charp_full_path;unsigned int ui4_len = 0;if(p_dir = opendir(dir_name) = NULL) printf(fail to open %s n,dir_name); printf( please check if %s is a folder, or check if the path is correct n,dir_name);return; printf(n %s traverse start : n,dir_name); printf(files under %s are : n,dir_name);while(p_dirent = readdir(p_dir) != NULL) if(strcmp(p_dirent->d_name,.) = 0) | (strcmp(p_dirent->d_name,.) = 0) contin
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2024年合作公司股权协议
- 2024年婚前协议与离婚协议的权益保障
- 2024年创意设计工作室设计师劳动合同
- 2024年广告发布合同及其权益
- 2024年健康合作:医疗资源共享协议
- 2024版工程项目融资保障合同样本
- 2024年医疗健康信息管理与服务合同
- 专利代理合同约定协议
- 果园土壤改良服务协议
- 2024年市场推广与销售合同
- 中国环卫机械行业市场发展态势及发展趋势与投资战略研究报告
- 当代社会政策分析 课件 第九章 妇女社会政策
- 2024新交管12123学法减分考试题库含答案
- 中国电信新一代智算数据中心基础设施技术方案白皮书
- 2024年职业技能“大数据考试”专业技术人员继续教育考试题库与答案
- 国家高新技术企业评定打分表
- 成语故事钻木取火
- MOOC 自然地理学-西北大学 中国大学慕课答案
- 计算机组成原理与汇编语言课后习题及作业答案
- 中华民族共同体
- 2024新能源集控中心储能电站接入技术方案
评论
0/150
提交评论