Linux C/C++ 利用scandir和alphasort遍历目录文件并排序

之前讲述了如何利用readdir/readdir_r,对指定目录进行遍历并输出,参见:Linux C 讲解系统调用readdir, readdir_r 以及如何遍历目录下的所有文件

这里讲述利用scandir和alphasort如何遍历指定目录,并对文件名排序输出。

scandir,alphasort,versionsort

scandir,alphasort,versionsort 可搭配用于扫描指定目录dirp(不含子目录)下,满足filter过滤模式的文件,返回的结果通过qsort排序存放到namelist数组中(由scandir函数调用malloc分配空间),比较子用的是compar。

函数原型

查看man scandir(3)

#include <dirent.h>

int scandir(const char *dirp, struct dirent ***namelist,
      int (*filter)(const struct dirent *),
      int (*compar)(const struct dirent **, const struct dirent **));

int alphasort(const void *a, const void *b);
int versionsort(const void *a, const void *b);

alphasort和versionsort

alphasort和versionsort 作为比较函数,原型相同,可传递给compar。其区别是,
1)遵循的标准不一样
scandir,alphasort和遵循POSIX.1-2008;
versionsort是GNU扩展;
也就是说,两者需要的宏定义不一样:alphasort需要_BSD_SOURCE || _SVID_SOURCE支持,versionsort需要_GNU_SOURCE支持。

2)实现时,调用的比较函数不一样
alphasort调用的是strcoll,versionsort调用的是strverscmp。

  • 对于strcoll:
    比较是基于字符串被解释为,适合当前语言环境的LC_COLLATE类别,也就是说大多数情况下,字符串是ASCII编码。

  • 对于strverscmp:
    strcmp会将文件jan1, jan2, ..., jan9, jan10,排成字典序jan1, jan10, ..., jan2, ..., jan9。而strverscmp将里面的数字做了修正,会得到jan1, jan2, ..., jan9, jan10这样的排序。
    其比较的字符串并非LC_COLLATE

  • LC_COLLATE的描述参见man setlocale(3)

LC_COLLATE
              for regular expression matching (it determines the  meaning  of  range
              expressions and equivalence classes) and string collation.

翻译一下:

对于正则表达式匹配 (它决定了范围表达式和等价类的含义)和字符串校勘。

从这里看不出什么,可参见这篇文章setlocale()函数详解——C语言,可知,用setlocale设置LC_COLLATE会影响strcoll和strxfrm,其C字符串是ASCII编码。

示例

用scandir和alphasort,scandir和versionsort 分别顺序、逆序打印指定目录下的文件名。
注意:打印文件的顺序,跟使用的比较函数无关,而是取决于变量存放结果的namelist的访问顺序。

#include <dirent.h>
#include <stdio.h>

/* 顺序打印指定目录下文件 */
void test_scandir1()
{
    struct dirent **namelist;
    int n;
    n = scandir(".", &namelist, NULL, alphasort);
    if (n < 0)
        perror("scandir error");
    else
    {
        for (int m = 0; m < n; ++m)
        {
            printf("%s\n", namelist[m]->d_name);
            free(namelist[m]);
        }
        free(namelist);
    }
}

/* 逆序打印指定目录下文件 */
void test_scandir2()
{
    struct dirent **namelist;
    int n;
    n = scandir(".", &namelist, NULL, versionsort);
    if (n < 0)
        perror("scandir error");
    else
    {
        while (n--)
        {
            printf("%s\n", namelist[n]->d_name);
            free(namelist[n]);
        }
        free(namelist);
    }
}

原文链接: https://www.cnblogs.com/fortunely/p/15869825.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;

也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬

    Linux C/C++ 利用scandir和alphasort遍历目录文件并排序

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/402751

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年4月21日 上午11:12
下一篇 2023年4月21日 上午11:12

相关推荐