按创建时间排序scandir()

时间:2014-11-10 06:33:17

标签: c posix

在我的程序中,我正在显示文件列表。现在我正在使用内置alphasort函数的scandir,但是我想根据创建日期进行排序。我写了自己的比较函数,但无论我测试它多少都行不通。这些项目以看似随机的顺序出现。有些可能是有序的,但最旧的文件可能会出现在中间。例如,假设我有来自ls的以下输出

Nov  9 22:39 file1
Nov  9 19:40 file2
Nov  9 19:39 file3
Nov  9 19:09 file4

然后我得到输出,既不是升序也不是降序。

file2
file1
file3
file4

我已经尝试了st_mtime和st_ctime,因为我知道有时创建日期不可用。如果我查看“ls -lt”的输出,那么我会看到所有文件,正确的时间,按正确的顺序排序 - 所以我知道文件包含我需要的信息。

int datesort(const struct dirent** file1, const struct dirent** file2) {
    struct stat info1, info2;
    stat((*file1)->d_name, &info1);
    stat((*file2)->d_name, &info2);

    double diff = difftime(info1.st_ctime, info2.st_ctime);
    if (diff<0) {return -1;}
    if (diff>0) {return 1;}
    if (diff==0) {return 0;}
}

3 个答案:

答案 0 :(得分:1)

d_name只是文件名,而不是文件路径。因此stat只有在您检查当前工作目录时才会成功。否则,您要么stat某个其他文件,它恰好与目标目录中的文件同名,或者scan将返回错误。

检查所有系统调用是否有错误返回是一个非常好的习惯。它可以节省许多小时的调试时间。

此外,即使更正了,该代码最终会在同一个文件上多次调用stat,这是非常低效的(尽管现代操作系统通常会缓存统计数据,甚至文件路径解析信息,所以它&#39 ;不像过去那样糟糕)。您最好使用readdir获取未分类的dirents向量,然后为每个文件收集stat一次,然后根据stat向量对文件向量进行排序。 (或者,您可以保留由inode索引的创建时间的哈希映射,但这样做的工作量更大。)

答案 1 :(得分:0)

找到了有效的实施方案

/* sortbydatetime - helper for scandir sorting */

static inline int
sortbydatetime(const struct dirent **a, const struct dirent **b)
{
    int rval;
    struct stat sbuf1, sbuf2;
    char path1[PATH_MAX], path2[PATH_MAX];

    snprintf(path1, PATH_MAX, "%s/%s", PRINT_SPOOLER_PATH, (*a)->d_name);
    snprintf(path2, PATH_MAX, "%s/%s", PRINT_SPOOLER_PATH, (*b)->d_name);

    rval = stat(path1, &sbuf1);
    if (rval) {
        perror("stat");
        return 0;
    }
    rval = stat(path2, &sbuf2);
    if (rval) {
        perror("stat");
        return 0;
    }

    return sbuf1.st_mtime < sbuf2.st_mtime;
}

这是来自

的SPOOL队列代码的一部分

https://github.com/vatlidak/cucs-sea-hmwk2/blob/master/src/showqueue.c#L30

答案 2 :(得分:0)

以上答案不正确。

返回sbuf1.st_mtime

如果sbuf1.st_mtime> sbuf2.st_mtime将返回0,并且返回0将导致不确定的订单

应为:

返回sbuf1.st_mtime-sbuf2.st_mtime;