Список каталогов с подстановочными знаками в C

Есть ли готовая функция в C, которая может перечислить содержимое каталога, используя wildcards для фильтрации имен файлов, например, эквивалент:

echo [!b]????

который показывает имена записей каталога, которые состоят из четырех символов и не начинаются с «b»?

Я знаю, что могу использовать scandir, но тогда мне нужно предоставить свою собственную функцию фильтра:

#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
int filter(const struct dirent *entry)
{
    if (strlen(entry->d_name) == 4 && entry->d_name[0] != 'b') return 1;
    else return 0;
}
void main(void)
{
    struct dirent **list;
    int           count;
    count=scandir(".", &list, filter, alphasort)-1;
    if (count < 0)
        puts("Cannot open directory");
    else
        for (; count >= 0; count--)
            puts(list[count]->d_name);
    free(list);
}

Честно говоря, я серьезно подумываю о том, чтобы позвонить shell, чтобы он сделал это за меня:

#include <stdio.h>
#include <stdlib.h>
void main(void)
{
    FILE *fp;
    char buffer[1024];
    fp=popen("echo [!b]???", "r");
    if (fp == NULL)
        puts("Failed to run command.");
    else
        while (fgets(buffer, sizeof(buffer), fp) != NULL)
            puts(buffer);
    pclose(fp);
}

person Ulrik    schedule 16.08.2016    source источник
comment
в чем проблема использовать регулярное выражение внутри фильтра функций?   -  person    schedule 16.08.2016
comment
Мне нужно поведение ls wildcard, которое не совсем похоже на регулярное выражение. Например: *.jpg означает любое количество любых символов, за которым следует точка-jpg, в то время как в регулярном выражении это будет означать любое количество ничего, за которым следует один символ любого типа, за которым следует jpg. Тогда эквивалент регулярного выражения равен .*\.jpg, не так ли?   -  person Ulrik    schedule 16.08.2016
comment
Возможно, вы ищете функцию glob. man 3 glob.   -  person Ian Abbott    schedule 16.08.2016
comment
Вы смотрели на fnmatch(), wordexp() или glob()?   -  person EOF    schedule 16.08.2016
comment
Благодарю вас! И fnmatch, и glob будут полезны для разных сценариев, которые у меня есть.   -  person Ulrik    schedule 16.08.2016
comment
Вы смотрели на popen() и read()?   -  person FredK    schedule 16.08.2016


Ответы (1)


Как упоминалось в комментариях, функция glob() была бы очень хороша для этого:

#include <stdio.h>
#include <glob.h>

int
main (void)
{
    int i=0;
    glob_t globbuf;

    if (!glob("[!b]????", 0, NULL, &globbuf)) {
        for (i=0;  i <globbuf.gl_pathc; i++) { 
            printf("%s ",globbuf.gl_pathv[i]);
        }
        printf("\n");
        globfree(&globbuf);
    } else 
        printf("Error: glob()\n");
}
person Pierz    schedule 29.09.2016