Three Ways to Find Files

Let’ say we have to implement a function that search a folder to recursively find files having an extension from a given list of extensions. This article shows three possible implementations: one using FindFirstFile and FindNextFile WinAPI functions, one using CFileFind MFC class and one using Filesystem Library.

Find files using FindFirstFile and FindNextFile WinAPI functions

Althugh this implementation uses some ATL stuff to make things easier, it appears still quite complicated.

void FindFiles(
    const CString& strRootPath,        // initial path to search
    const std::list<CString> listExt,  // a list of file extensions
    std::list<CString>& listFiles)     // output list of files found
{
    CString strFileToFind = strRootPath;
    ATLPath::Append(CStrBuf(strFileToFind, MAX_PATH), _T("*.*"));

    WIN32_FIND_DATA findData = { 0 };
    HANDLE hFileFind = ::FindFirstFile(strFileToFind, &findData);
    if (INVALID_HANDLE_VALUE != hFileFind)
    {
        do
        {
            CString strFileName = findData.cFileName;
            if ((strFileName == _T(".")) || (strFileName == _T("..")))
                continue;

            CString strFilePath = strRootPath;
            ATLPath::Append(CStrBuf(strFilePath, MAX_PATH), strFileName);
            if (ATLPath::IsDirectory(strFilePath))
            {
                // call recursive
                FindFiles(strFilePath, listExt, listFiles);
            }
            else
            {
                CString strExt = ATLPath::FindExtension(strFilePath);
                strExt.TrimLeft(_T('.'));

                if (IsStringInListNoCase(strExt, listExt))
                {
                    listFiles.push_back(strFilePath);
                }
            }

        } while (::FindNextFile(hFileFind, &findData));

        ::FindClose(hFileFind);
    }
}

Find files using CFileFind MFC class

Using CFileFind MFC class can make code a little bit shorter and the programmer’s life easier.

void FindFiles(
    const CString& strRootPath,        // initial path to search
    const std::list<CString> listExt,  // a list of file extensions
    std::list<CString>& listFiles)     // output list of files found
{
    CString strFileToFind = strRootPath + _T("\\*.*");

    CFileFind fileFind;
    BOOL bMoreFiles = fileFind.FindFile(strFileToFind);
    while (bMoreFiles)
    {
        bMoreFiles = fileFind.FindNextFile();
        if (fileFind.IsDots())
            continue;

        CString strFilePath = fileFind.GetFilePath();
        if (fileFind.IsDirectory())
        {
            // call recursive
            FindFiles(strFilePath, listExt, listFiles);
        }
        else
        {
            int nPos = strFilePath.ReverseFind(_T('.'));
            if (-1 != nPos)
            {
                CString strExt = strFilePath.Right(strFilePath.GetLength() - nPos - 1);
                if (IsStringInListNoCase(strExt, listExt))
                {
                    listFiles.push_back(strFilePath);
                }
            }
        }
    }
}

Note: IsStringInListNoCase searches a list for a string, not case sensitive. You can find its implementation in the attached demo solution.

Find files using Filesystem Library

Here it is:

void FindFiles(
    const CString& strRootPath,        // initial path to search
    const std::list<CString> listExt,  // a list of file extensions
    std::list<CString>& listFiles)     // output list of files found
{
    _FSPFX path root_path(strRootPath.GetString());
    _FSPFX recursive_directory_iterator end;
    _FSPFX recursive_directory_iterator iter(root_path);
    while (iter != end)
    {
        const auto& path = iter->path();
        CString strExt = path.extension().c_str();
        strExt.TrimLeft(_T('.'));
        if (IsStringInListNoCase(strExt, listExt))
        {
            listFiles.push_back(path.c_str());
        }
        ++iter;
    }
}

Hurray, we did it in just few lines of code! 🙂
Of course, it can be used in MFC, ATL, Win32 and Console applications, as well.

Demo solution

The demo solution contains three projects, each having one of the above implementations.
Download: Find Files Samples (Visual Studio 2015).zip (1195 downloads)

Resources and related articles

1 thought on “Three Ways to Find Files”

  1. Hi Ovidiu Cucu, I would like to search particular file type(.cpp and .cxx) from the directory which included couple of sub-folders.
    The purpose is to add some code into these files(cpp. and cxx) in particular line. could you please help to provide an example as reference? appreciated and thank you very much!

    Reply

Leave a Comment