sort files by ascii order

1.2k views Asked by At

I'm trying to code a simple function to sort the content of a directory. The Thing is, it comes out in alphabetical order, regardless of uppercase or lowercase. I'd like to sort this content in ASCII order.

example: I got 4 files, named Art, boat, Cat and donkey. My actual code sort them in this order, while i'd like to get Art, Cat, boat and donkey.

void    list_dir(char *str){
DIR *rep = NULL;
struct dirent* read_file = NULL;

rep = opendir(str);
if (!rep)
{
    ft_putstr("ft_ls: ");
    perror(str);
    ft_putchar('\n');
}
while((read_file = readdir(rep)) != NULL)
{
    if (read_file->d_name[0] != '.')
    {
        ft_putstr(read_file->d_name);
        ft_putchar('\n');
    }
}

}

2

There are 2 answers

0
mirabilos On

readdir(3) does not normally sort at all, it lists the entries in directory order. If the list is sorted, either the files were created sorted, or the OS sorts them.

In order to sort the output yourself, put the list of names into an array then sort it e.g. with qsort(3) and strcmp(3).

Alternatively, just pipe the output through sort(1). Do make sure that the LC_COLLATION environment variable is set proper. For example, run ./yourprogram | (unset LC_ALL; LC_CTYPE=en_US.UTF-8 LC_COLLATE=C sort).

0
peihan On

By calling scandir with user defined filter & comparator is a simple solution imho. Here is the code:

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

static int my_dir_filter(const struct dirent* dir);
static int my_dir_comparator(const struct dirent**, const struct dirent**);

int main(int argc, char* const* argv) {
    struct dirent** ent_list_ = NULL;
    int r = scandir(".", &ent_list_, my_dir_filter, my_dir_comparator);
    for (int i = 0; i < r; ++i)
        printf("No. %-3d [%s]\n", i + 1, ent_list_[i]->d_name);
    for (int i = 0; i < r; ++i)
        free(ent_list_[i]);
    free(ent_list_);
    return r < 0 ? 1 : 0;
}

int my_dir_filter(const struct dirent* dir) {
    return (dir->d_type == DT_REG) ? 1 : 0;
}

int my_dir_comparator(const struct dirent** lhs, const struct dirent** rhs) {
    return strcasecmp((*lhs)->d_name, (*rhs)->d_name);
}

And test result:

$ ls|LANG=C sort   ## in ASCII order
Art
Cat
boat
donkey
$ ../a.out         ## in my_dir_comparator order
No. 1   [Art]
No. 2   [boat]
No. 3   [Cat]
No. 4   [donkey]