引言
在Linux系统编程中,目录操作是一个常见的任务。本文将详细介绍scandir
, scandirat
, alphasort
, 和 versionsort
这几个用于目录扫描的函数。我们将从函数原型、参数说明、返回值,到内存分配等方面进行全面解析。
正如Bjarne Stroustrup在《The C++ Programming Language》中所说:“程序设计不仅仅是我们告诉计算机要做什么,更是关于我们如何组织复杂性。”
scandir函数详解
函数原型
#include <dirent.h> int scandir(const char *dirp, struct dirent ***namelist, int (*filter)(const struct dirent *), int (*compar)(const struct dirent **, const struct dirent **));
参数说明
- dirp:指定扫描的目录
- namelist:struct dirent结构体类型的三级指针,用于获取该函数内部为存放返回结果的分配的动态内存,动态分配内存结构如图2-1所示.
- filter:函数指针,指向过滤模式函数,当filter指针设置为NULL时,扫描dirp目录下的所有顶层文件.该函数有一个参数const struct dirent *是指在遍历过程中所遍历到的每一个子目录dirent,filter可以根据dirent的类型、名称等信息来判定当前的dirent是否为合法的子目录,合法则函数返回0,则该子目录的名称会被存储在namelist中;否则返回非0,则该子目录被过滤掉。
- compar:函数指针,指向对遍历结果进行排序函数,alphasort函数和versionsort是经常用到的函数.
内存分配(Memory Allocation)
如图2-1所示,分配的内存包含两个部分:
- 一部分是struct dirent类型指针(一段连续内存,可看成指针数组),用于指向malloc分配用来存放目录信息内存地址,
- 另一部分是malloc分配struct dirent大小内存,存放遍历目录或文件的相关信息。
若想获取目录相关信息,需要先获取指向该存放内存的指针,即图2-1中的strcut dirent *arr[N]指针数组地址。
返回值
scandir() 函数返回被选择的目录条数,或者如果出错返回 -1。
scandirat函数详解
函数原型
#include <fcntl.h> /* Definition of AT_* constants */ #include <dirent.h> int scandirat(int dirfd, const char *dirp, struct dirent ***namelist, int (*filter)(const struct dirent *), int (*compar)(const struct dirent **, const struct dirent **));
描述
scandirat()
是scandir()
的扩展函数,主要区别在于第一个参数dirfd
与第二个参数dirp
。
如果dirp是一个绝对路径的字符串,则函数无视参数dirfd,功能与scandir()一致。
如果dirp是一个相对路径的字符串,且参数dirfd的值是AT_FDCWD (#include ),则表示从应用程序当前的工作路径拼接上dirp的相对路径所组成的绝对路径下去遍历;
当dirfd值不为AT_FDCWD时而是一个代替文件夹的file descriptor(参考dirfd(DIR*))时,则遍历的文件夹路径即为dirfd所指向的文件夹再拼接上dirp的相对路径所组成的绝对路径。
示例
#define _DEFAULT_SOURCE #include <dirent.h> #include <stdio.h> #include <stdlib.h> int main(void) { struct dirent **namelist; int n; n = scandir(".", &namelist, NULL, alphasort); if (n == -1) { perror("scandir"); exit(EXIT_FAILURE); } while (n--) { printf("%s\n", namelist[n]->d_name); free(namelist[n]); //------------------------>①每访问完一条目录或文件信息,释放由malloc分配的用于存放该信息的动态内存 } free(namelist); //------------------------>②访问完指定目录下所有目录或文件信息内容,释放malloc分配的用于索引的指针数组内存 exit(EXIT_SUCCESS); }
排序函数:alphasort和versionsort
alphasort
int alphasort(const struct dirent **a, const struct dirent **b);
alphasort()
的实现是把dirent
的名称用strcoll()
进行比较。
versionsort
int versionsort(const struct dirent **a, const struct dirent **b);
versionsort()
的实现是把dirent
的名称用strverscmp()
进行比较。
排序函数的不同点
- alphasort()的实现是把dirent的名称用strcoll()进行比较,排序的结果是按ASCII编码的值由小到大排序。
- versionsort()的实现是把dirent的名称strverscmp()进行比较,排序的结果是也按ASCII编码的值由小到大排序,不同的是支持对名称中按数字序号的排序。
返回值
alphasort() 和 versionsort() 函数返回一个小于、等于或大于零的整数,当第一个参数被认为是小于、等于或大于第二个参数时.
总结
在本文中,我们详细介绍了Linux系统中用于目录扫描的几个重要函数。这些函数不仅在文件系统操作中有广泛应用,也是理解Linux系统编程的关键。
正如古人所说:“探索无止境,学无止境。”在编程的世界里,每一个函数、每一个接口都是一个新世界,值得我们去探索和理解。
结语
在我们的编程学习之旅中,理解是我们迈向更高层次的重要一步。然而,掌握新技能、新理念,始终需要时间和坚持。从心理学的角度看,学习往往伴随着不断的试错和调整,这就像是我们的大脑在逐渐优化其解决问题的“算法”。
这就是为什么当我们遇到错误,我们应该将其视为学习和进步的机会,而不仅仅是困扰。通过理解和解决这些问题,我们不仅可以修复当前的代码,更可以提升我们的编程能力,防止在未来的项目中犯相同的错误。
我鼓励大家积极参与进来,不断提升自己的编程技术。无论你是初学者还是有经验的开发者,我希望我的博客能对你的学习之路有所帮助。如果你觉得这篇文章有用,不妨点击收藏,或者留下你的评论分享你的见解和经验,也欢迎你对我博客的内容提出建议和问题。每一次的点赞、评论、分享和关注都是对我的最大支持,也是对我持续分享和创作的动力。