поиск имени файла, используя только расширение

#c #linux

#c #linux

Вопрос:

предыдущая проблема была плохо описана. Мне нужно получить имя файла и присвоить это имя переменной. Единственное, что файл может иметь любое имя. То, что я знаю, это расширение файла, и может быть только один файл с этим расширением. Есть ли какой-либо способ реализовать это на C?

Обновление # 1 Расширением файла является *.knb , а целью является система Linux.

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

#define LOG_() do{fprintf(stdout, " UNIT TESTING...n");}while(0)

char* knbname;

void fName(void);

int main()
{
     LOG_();
     fName(void);

     //do some more code 

return 0;
}

void fName(void){
     DIR           *d;
     struct dirent *dir;
     d = opendir(".");
     if (d)
     {
        //find file with *.knb extension and place name into knbname
     }
     closedir(d);
}
 

Я не знаю, как найти *.knb файл в функции fName() и как присвоить имя knbname . Любая помощь будет оценена

Комментарии:

1. Добавьте while( (dir = readdir(d)) != NULL ) цикл и сравните значение dir->d_name . (Обратите внимание, что «dir», вероятно, не лучшее имя для struct dirent , поскольку запись каталога не обязательно является каталогом, и на самом деле вам, вероятно, наплевать на каталоги, если вы не хотите выполнять рекурсивный спуск.)

2. В цикле, предложенном @WilliamPursell, вы можете затем проанализировать каждое имя записи каталога с strtok() помощью (используя ‘.’ в качестве разделителя), пока не найдете нужное расширение.

3. OT: не выстраивайте свои переменные таким образом. Что произойдет, если вам нужно изменить тип переменной? Как насчет того, когда это несколько переменных? Вы потратите много времени, просто заставляя их выстраиваться снова. Это время, потраченное на ничего полезного.

4. Вы можете использовать POSIX nftw() для обхода дерева каталогов. Вы могли бы использовать fnmatch() для сопоставления с именем файла glob.

5. Нет необходимости, даже strtok() если вы ищете только суффикс, можно просто использовать strcmp() нацеленный на хвостовую часть строки в правильном положении в зависимости от длины.

Ответ №1:

Вы заново изобретаете glob() функцию POSIX. Вот пример того, как его использовать (дополнительные параметры см. в разделе Флаги в manpage):

 #include <glob.h>

int main(void)
{
    glob_t glob_res = { 0 };

    glob("*.knb", 0, NULL, amp;glob_res);
    if (glob_res.gl_pathc == 0) puts("No match.");
    else printf("First match is %sn", glob_res.gl_pathv[0]);

    globfree(amp;glob_res);
    return 0;
}

 

Ответ №2:

После того, как Эндрю указал на некоторые серьезные недостатки в предыдущем дизайне, я сделаю еще одну попытку решения…

 int hasExtension(char *filename, char *extension);

int main(void)
{
    DIR *directory;
    struct dirent *entry;

    if(NULL == (directory = opendir(".")))
    {
        perror("Failed to open directoryn");
        exit(1);
    }
    
    while( NULL != (entry = readdir(directory)) )
    {
        if(DT_REG == entry->d_type) { // Regualar files only
            if(hasExtension(entry->d_name, ".knb"))
            {
                printf("Match     - %sn", entry->d_name);
            } else {
                printf("No match  - %sn", entry->d_name);
            }
        }
    }
    closedir(directory);

    return 0;
}

int hasExtension(char *filename, char *extension)
{
    size_t filename_len, extension_len;

    if((NULL == filename) || (NULL ==extension))
        return 0;

    filename_len = strlen(filename);
    extension_len = strlen(extension);

    if(filename_len < extension_len)
        return 0;

    return !strcmp(filename   filename_len - extension_len, extension);
}
 

Комментарии:

1. И если filename это .. или xxx ?

2. Эндрю, да, теперь я понимаю… вы бы вышли за пределы границ… 🙁 Плохая идея…

3. На самом деле функция hasExtension должна быть переработана / переименована в strEndsWith (строка заканчивается на), что в основном и делает, и там, делая код более универсальным / многоразовым.