ls如何排序文件名?

cl001

我正在尝试编写一个函数,该函数模仿Unix中ls命令的输出。我最初尝试使用scandir和alphasort执行此操作,并且确实确实在目录中打印了文件,并且对它们进行了排序,但是由于某种原因,此排序列表似乎与文件名的“排序列表”不匹配ls给的。

例如,如果我有一个包含file.c,FILE.c和ls.c的目录。

ls按以下顺序显示它们:file.c FILE.c ls.c但是当我使用alphasort / scandir对其进行排序时,它对它们的排序方式为:FILE.c file.c ls.c

请问ls如何对目录中的文件进行排序,从而得到不同顺序的结果?

名义动物

若要模拟默认ls -1行为,请通过调用使您的程序具有区域设置意识

setlocale(LC_ALL, "");

在您的开头附近main(),然后使用

count = scandir(dir, &array, my_filter, alphasort);

wheremy_filter()是一个函数,该函数以点号开头的名称返回0 .,而其他所有名称返回1。alphasort()是POSIX函数,它使用语言环境排序顺序,与相同strcoll()

基本的实现方式类似于

#define  _POSIX_C_SOURCE 200809L
#define  _ATFILE_SOURCE
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <locale.h>
#include <string.h>
#include <dirent.h>
#include <stdio.h>
#include <errno.h>

static void my_print(const char *name, const struct stat *info)
{
    /* TODO: Better output; use info too, for 'ls -l' -style output? */
    printf("%s\n", name);
}

static int my_filter(const struct dirent *ent)
{
    /* Skip entries that begin with '.' */
    if (ent->d_name[0] == '.')
        return 0;

    /* Include all others */
    return 1;
}

static int my_ls(const char *dir)
{
    struct dirent **list = NULL;
    struct stat     info;
    DIR            *dirhandle;
    int             size, i, fd;

    size = scandir(dir, &list, my_filter, alphasort);
    if (size == -1) {
        const int cause = errno;

        /* Is dir not a directory, but a single entry perhaps? */
        if (cause == ENOTDIR && lstat(dir, &info) == 0) {
            my_print(dir, &info);
            return 0;
        }

        /* Print out the original error and fail. */
        fprintf(stderr, "%s: %s.\n", dir, strerror(cause));
        return -1;
    }

    /* We need the directory handle for fstatat(). */
    dirhandle = opendir(dir);
    if (!dirhandle) {
        /* Print a warning, but continue. */
        fprintf(stderr, "%s: %s\n", dir, strerror(errno));
        fd = AT_FDCWD;
    } else {
        fd = dirfd(dirhandle);
    }

    for (i = 0; i < size; i++) {
        struct dirent *ent = list[i];

        /* Try to get information on ent. If fails, clear the structure. */
        if (fstatat(fd, ent->d_name, &info, AT_SYMLINK_NOFOLLOW) == -1) {
            /* Print a warning about it. */
            fprintf(stderr, "%s: %s.\n", ent->d_name, strerror(errno));
            memset(&info, 0, sizeof info);
        }

        /* Describe 'ent'. */
        my_print(ent->d_name, &info);
    }

    /* Release the directory handle. */
    if (dirhandle)
        closedir(dirhandle);

    /* Discard list. */
    for (i = 0; i < size; i++)
        free(list[i]);
    free(list);

    return 0;
}

int main(int argc, char *argv[])
{
    int arg;

    setlocale(LC_ALL, "");

    if (argc > 1) {
        for (arg = 1; arg < argc; arg++) {
            if (my_ls(argv[arg])) {
                return EXIT_FAILURE;
            }
        }
    } else {
        if (my_ls(".")) {
            return EXIT_FAILURE;
        }
    }

    return EXIT_SUCCESS;
}

请注意,由于我不想让您仅复制和粘贴代码,因此我故意使此操作超出了您实际需要的严格要求。您可以更轻松地编译,运行和研究该程序,然后移植所需的更改-可能只是setlocale("", LC_ALL);一行!-对您自己的程序,而不是尝试向您的老师/讲师/ TA解释为什么代码看起来像是从其他地方逐字复制的。

上面的代码甚至适用于在命令行(该cause == ENOTDIR部分)上指定的文件它还使用单个功能my_print(const char *name, const struct stat *info)来打印每个目录条目。为此,它确实要求stat每个条目。

如果不建立路径目录条目和调用的lstat()my_ls()打开一个目录句柄,并使用fstatat(descriptor, name, struct stat *, AT_SYMLINK_NOFOLLOW)聚集在基本相同的方式,信息lstat()会,但name作为开始,按指定的目录的相对路径descriptordirfd(handle)如果handle是一个开放的DIR *)。

的确,为每个目录条目调用stat函数之一是“缓慢的”(特别是如果您进行/bin/ls -1样式输出)。但是,的产出ls是供人类消费的;并且经常通过管道传送,moreless让人们随意观看。这就是为什么我个人认为“额外” stat()调用(即使不是真正需要的)在这里也不成问题的原因。我认识的大多数人类用户ls -l还是会使用或(我最喜欢的)ls -laF --color=autoauto这意味着仅当标准输出为终端时才使用ANSI颜色;即当时isatty(fileno(stdout)) == 1。)

换句话说,既然您已经有了ls -1订单,我建议您将输出修改为类似于ls -l(破折号,而不是破折号)。您只需要为此进行修改my_print()

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

排序文件的FireStore

如何在R中创建具有顺序文件名和数字的向量?

如何在ruby中对文件名进行排序?

Python:在目录中排序文件名,并在每个文件名的开头添加一个数字

排序文件名的子字符串,提供唯一值

如何使用LINQ使用条件通过子字符串排序文件名?

如何从ls输出中检索文件名

如何导入具有排序文件名的csv文件?

如何根据文件名将文件名排序到文件夹中

如何遍历ls命令返回的某些文件名?

'ls -1':如何列出不带扩展名的文件名

如何使Shell识别由`ls -A`命令返回的文件名,并且这些文件名包含空格?

ls列出按文件名排序的文件,不带扩展名

GNU排序文件名的前缀和一位或两位数

Linux结合按创建日期和给定文件名排序文件

如何对使用Directoryinfo读取的文件名进行排序

重复作业的顺序文件名

如何按文件名中的日期对文件排序?

如何使ls按文件扩展名排序然后命名?

如何使用bash排序文件

排序文件名| uniq>输出不会删除重复项

如何对多个文件名部分上的文件进行排序?

如何在Python中创建顺序文件名

ls文件名如何按数字顺序在文件名中包含空格字符

如何从 ls 获取全名、路径和文件名?

在bash中重命名文件时重新排序文件名中的子字符串?

如何从ls -l的结果中隔离文件权限和文件名?

LS - 按日期排序,只显示文件名

如何从 minio (mc) ls 获取文件名