【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系统编程的关键。

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

结语

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

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

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

目录
相关文章
|
1天前
|
关系型数据库 MySQL Linux
Linux系统如何设置自启动服务在MySQL数据库启动后执行?
【10月更文挑战第25天】Linux系统如何设置自启动服务在MySQL数据库启动后执行?
22 3
|
1天前
|
Linux Shell
Linux系统
是对Linux系统进行管理的命令。对于Linux系统来说,无论是中央处理器、内存、磁盘驱动器、键盘、鼠标,还是用户等都是文件,Linux系统管理的命令是它正常运行的核心,与之前的DOS命令类似。linux命令在系统中有两种类型:内置Shell命令和Linux命令。
|
3天前
|
Linux Shell
Linux系统
是对Linux系统进行管理的命令。对于Linux系统来说,无论是中央处理器、内存、磁盘驱动器、键盘、鼠标,还是用户等都是文件,Linux系统管理的命令是它正常运行的核心,与之前的DOS命令类似。linux命令在系统中有两种类型:内置Shell命令和Linux命令。Linux系统
|
2天前
|
Linux Shell
Linux系统
是对Linux系统进行管理的命令。对于Linux系统来说,无论是中央处理器、内存、磁盘驱动器、键盘、鼠标,还是用户等都是文件,Linux系统管理的命令是它正常运行的核心,与之前的DOS命令类似。linux命令在系统中有两种类型:内置Shell命令和Linux命令。
|
2天前
|
运维 监控 Shell
深入理解Linux系统下的Shell脚本编程
【10月更文挑战第24天】本文将深入浅出地介绍Linux系统中Shell脚本的基础知识和实用技巧,帮助读者从零开始学习编写Shell脚本。通过本文的学习,你将能够掌握Shell脚本的基本语法、变量使用、流程控制以及函数定义等核心概念,并学会如何将这些知识应用于实际问题解决中。文章还将展示几个实用的Shell脚本例子,以加深对知识点的理解和应用。无论你是运维人员还是软件开发者,这篇文章都将为你提供强大的Linux自动化工具。
|
5月前
|
消息中间件 存储 缓存
【嵌入式软件工程师面经】Linux系统编程(线程进程)
【嵌入式软件工程师面经】Linux系统编程(线程进程)
122 1
|
6月前
|
Linux 调度 数据库
Linux下的系统编程——线程同步(十三)
Linux下的系统编程——线程同步(十三)
100 0
Linux下的系统编程——线程同步(十三)
|
存储 Linux 调度
Linux系统编程 多线程基础
Linux系统编程 多线程基础
61 1
|
6月前
|
存储 安全 数据管理
Linux系统编程教程之Linux线程函数的使用:讲解Linux线程函数
Linux系统编程教程之Linux线程函数的使用:讲解Linux线程函数
61 1
|
6月前
|
NoSQL Unix Linux
Linux下的系统编程——守护进程、线程(十二)
Linux下的系统编程——守护进程、线程(十二)
69 0
Linux下的系统编程——守护进程、线程(十二)