【Linux系统编程】深入理解Linux目录扫描函数:scandir目录函数(按条件扫描目录

简介: 【Linux系统编程】深入理解Linux目录扫描函数:scandir目录函数(按条件扫描目录

引言

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所示,分配的内存包含两个部分:

  1. 一部分是struct dirent类型指针(一段连续内存,可看成指针数组),用于指向malloc分配用来存放目录信息内存地址,
  2. 另一部分是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系统编程的关键。

正如古人所说:“探索无止境,学无止境。”在编程的世界里,每一个函数、每一个接口都是一个新世界,值得我们去探索和理解。

结语

在我们的编程学习之旅中,理解是我们迈向更高层次的重要一步。然而,掌握新技能、新理念,始终需要时间和坚持。从心理学的角度看,学习往往伴随着不断的试错和调整,这就像是我们的大脑在逐渐优化其解决问题的“算法”。

这就是为什么当我们遇到错误,我们应该将其视为学习和进步的机会,而不仅仅是困扰。通过理解和解决这些问题,我们不仅可以修复当前的代码,更可以提升我们的编程能力,防止在未来的项目中犯相同的错误。

我鼓励大家积极参与进来,不断提升自己的编程技术。无论你是初学者还是有经验的开发者,我希望我的博客能对你的学习之路有所帮助。如果你觉得这篇文章有用,不妨点击收藏,或者留下你的评论分享你的见解和经验,也欢迎你对我博客的内容提出建议和问题。每一次的点赞、评论、分享和关注都是对我的最大支持,也是对我持续分享和创作的动力。

目录
相关文章
|
3天前
|
IDE Linux 开发工具
Linux 系统上安装
在Linux和Mac上安装Lua 5.3.0只需下载源码,解压,编译和安装。Windows用户可选择SciTE IDE或通过LuaForWindows在Github或Google Code下载安装。创建 HelloWorld.lua,使用`lua HelloWorld.lua`运行显示&quot;Hello World!&quot;。另可参考LuaDist官方推荐方式安装。
|
1天前
|
运维 Linux
CentOS系统openssh-9,你会的还只有初级Linux运维工程师的技术吗
CentOS系统openssh-9,你会的还只有初级Linux运维工程师的技术吗
|
2天前
|
监控 JavaScript Linux
Linux系统之部署Homepage个人导航页
【5月更文挑战第13天】Linux系统之部署Homepage个人导航页
21 1
|
3天前
|
监控 JavaScript 网络协议
Linux系统之安装uptime-kuma服务器监控面板
【5月更文挑战第12天】Linux系统之安装uptime-kuma服务器监控面板
14 0
|
3天前
|
Linux C语言 调度
|
3天前
|
Linux Perl
Linux系统的文本处理
Linux系统的文本处理
|
3天前
|
NoSQL Unix Linux
Linux下的系统编程——守护进程、线程(十二)
Linux下的系统编程——守护进程、线程(十二)
43 0
Linux下的系统编程——守护进程、线程(十二)
|
3天前
|
存储 Linux Shell
Linux系统编程(守护进程)
Linux系统编程(守护进程)
33 0
|
存储 Linux 调度
linux系统编程(十)守护进程、线程(下)
linux系统编程(十)守护进程、线程
136 0
|
NoSQL Ubuntu Unix
linux系统编程(十)守护进程、线程(上)
linux系统编程(十)守护进程、线程
240 0
linux系统编程(十)守护进程、线程(上)