Как рекурсивно пройти каталоги в C на Windows - PullRequest
6 голосов
/ 11 января 2010

В конечном итоге я хочу просмотреть файлы и подкаталоги папки и записать что-нибудь во все найденные файлы с определенным расширением (.wav в моем случае). когда я зацикливаюсь, как определить, является ли элемент, в котором я нахожусь, каталогом?

Ответы [ 5 ]

7 голосов
/ 11 января 2010

Вот как вы это делаете (это все из памяти, поэтому могут быть ошибки):

void FindFilesRecursively(LPCTSTR lpFolder, LPCTSTR lpFilePattern)
{
    TCHAR szFullPattern[MAX_PATH];
    WIN32_FIND_DATA FindFileData;
    HANDLE hFindFile;
    // first we are going to process any subdirectories
    PathCombine(szFullPattern, lpFolder, _T("*"));
    hFindFile = FindFirstFile(szFullPattern, &FindFileData);
    if(hFindFile != INVALID_HANDLE_VALUE)
    {
        do
        {
            if(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
            {
                // found a subdirectory; recurse into it
                PathCombine(szFullPattern, lpFolder, FindFileData.cFileName);
                FindFilesRecursively(szFullPattern, lpFilePattern);
            }
        } while(FindNextFile(hFindFile, &FindFileData));
        FindClose(hFindFile);
    }

    // Now we are going to look for the matching files
    PathCombine(szFullPattern, lpFolder, lpFilePattern);
    hFindFile = FindFirstFile(szFullPattern, &FindFileData);
    if(hFindFile != INVALID_HANDLE_VALUE)
    {
        do
        {
            if(!(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
            {
                // found a file; do something with it
                PathCombine(szFullPattern, lpFolder, FindFileData.cFileName);
                _tprintf_s(_T("%s\n"), szFullPattern);
            }
        } while(FindNextFile(hFindFile, &FindFileData));
        FindClose(hFindFile);
    }
}

Так что вы можете назвать это как

FindFilesRecursively(_T("C:\\WINDOWS"), _T("*.wav"));

чтобы найти все * .wav файлы в C: \ WINDOWS и его подкаталогах.

Технически вам не нужно делать два вызова FindFirstFile (), но я считаю, что функции сопоставления с образцом, которые предоставляет Microsoft (т. Е. PathMatchFileSpec или что-то еще), не так способны, как FindFirstFile (). Хотя для "* .wav" это, вероятно, было бы хорошо.

3 голосов
/ 11 января 2010

Исходя из вашего упоминания .wav, я собираюсь предположить, что вы пишете код для Windows (кажется, именно там *.wav файлы являются наиболее распространенными). В этом случае вы используете FindFirstFile и FindNextFile для обхода каталогов. Они используют структуру WIN32_FIND_DATA, которая имеет член dwFileAttributes, который содержит флаги, указывающие атрибуты файла. Если dwAttributes & FILE_ATTRIBUTE_DIRECTORY не ноль, у вас есть имя каталога.

1 голос
/ 15 марта 2012

Очень полезно. В любом случае у меня было переполнение стека, так как оно всегда добавляло "." на путь и возвращаясь к тому же пути = бесконечный цикл.

Добавление этого решило это:

// found a subdirectory; recurse into it PathCombine(szFullPattern, lpFolder, FindFileData.cFileName); FindFilesRecursively(szFullPattern, lpPattern); if (FindFileData.cFileName[0] == '.') continue;

0 голосов
/ 11 января 2010
0 голосов
/ 11 января 2010

opendir и readdir (в unix), вот пример:

http://opengroup.org/onlinepubs/007908775/xsh/readdir.html

или FindFirstFile в Windows

Вы также можете использовать оболочку довольно легко:

find . -name "*.wav"

or

ls **/*.wav    (in zsh and newer bashes)
...