Рекурсивный обход каталога. Какие библиотеки и функции использовать?
Универсально вряд ли возможно, так как Си не содержит CRT функций для поиска файлов.
Если винда, то FindFirstFileA и FindNextFileA из windows.h
https://msdn.microsoft.com/ru-ru/library/windows/d...
https://msdn.microsoft.com/ru-ru/library/windows/d...typedef void (*LPSEARCHFUNC)(LPCTSTR lpszFileName);

BOOL SearchFiles(LPCTSTR lpszFileName, LPSEARCHFUNC lpSearchFunc, BOOL bInnerFolders = TRUE)
{
    LPTSTR part;
    char tmp[MAX_PATH]; 
    char name[MAX_PATH];

    HANDLE hSearch = NULL;
    WIN32_FIND_DATA wfd;
    memset(&wfd, 0, sizeof(WIN32_FIND_DATA));

    
    if(bInnerFolders)
    {
        if(GetFullPathName(lpszFileName, MAX_PATH, tmp, &part) == 0) return FALSE;
        lstrcpy(name, part);
        lstrcpy(part, "*.*");

        
        wfd.dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY;
        if (!((hSearch = FindFirstFile(tmp, &wfd)) == INVALID_HANDLE_VALUE))
        do
        {
            if (!strncmp(wfd.cFileName, ".", 1) || !strncmp(wfd.cFileName, "..", 2))            
            continue;
        
            if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
            {
                char next[MAX_PATH];
                if(GetFullPathName(lpszFileName, MAX_PATH, next, &part) == 0) return FALSE;
                lstrcpy(part, wfd.cFileName);
                lstrcat(next, "\\");
                lstrcat(next, name);

                SearchFiles(next, lpSearchFunc, TRUE);
            }
        }
        while (FindNextFile(hSearch, &wfd));

        FindClose (hSearch); 
    }

    if ((hSearch = FindFirstFile(lpszFileName, &wfd)) == INVALID_HANDLE_VALUE) 
        return TRUE;
    do
    if (!(wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) 
    {
        char file[MAX_PATH];
        if(GetFullPathName(lpszFileName, MAX_PATH, file, &part) == 0) return FALSE;
        lstrcpy(part, wfd.cFileName);

        lpSearchFunc(file);
    }
    while (FindNextFile(hSearch, &wfd));
    FindClose (hSearch); 

    return TRUE;
}
Как находит файл по маске, вызывает функцию по указателю с прототипом:
void FileFound(LPCTSTR lpszFileName)
Не знаю как в C, но в некоторых языках есть функция walk(), которая возвращает список диреторий и поддиректорий в указанной директории golang.org/pkg/path/filepath/#Walk