Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to recursively traverse directories in C on Windows

Ultimately I want to travel through a folder's files and subdirectories and write something to all files i find that have a certain extension(.wav in my case). when looping how do i tell if the item I am at is a directory?

like image 561
pmilb Avatar asked Jan 10 '10 22:01

pmilb


People also ask

How do I search for a directory in recursively?

An easy way to do this is to use find | egrep string . If there are too many hits, then use the -type d flag for find. Run the command at the start of the directory tree you want to search, or you will have to supply the directory as an argument to find as well. Another way to do this is to use ls -laR | egrep ^d .

Which command is used to recursively?

Linux recursive directory listing using ls -R command. The -R option passed to the ls command to list subdirectories recursively.

How do I get a list of files in a folder?

Press and hold the SHIFT key and then right-click the folder that contains the files you need listed. Click Open command window here on the new menu. A new window with white text on a black background should appear. o To the left of the blinking cursor you will see the folder path you selected in the previous step.


2 Answers

Here is how you do it (this is all from memory so there may be errors):

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);
    }
}

So you could call this like

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

to find all the *.wav files in C:\WINDOWS and its subdirectories.

Technically you don't have to do two FindFirstFile() calls, but I find the pattern matching functions Microsoft provides (i.e. PathMatchFileSpec or whatever) aren't as capable as FindFirstFile(). Though for "*.wav" it would probably be fine.

like image 164
Luke Avatar answered Sep 22 '22 22:09

Luke


Based on your mention of .wav, I'm going to guess you're writing code for Windows (that seems to be where *.wav files are most common). In this case, you use FindFirstFile and FindNextFile to traverse directories. These use a WIN32_FIND_DATA structure, which has a member dwFileAttributes that contains flags telling the attributes of the file. If dwAttributes & FILE_ATTRIBUTE_DIRECTORY is non-zero, you have the name of a directory.

like image 31
Jerry Coffin Avatar answered Sep 21 '22 22:09

Jerry Coffin