Bob Moore's Coding Tips

2. How do I recurse through a directory tree?

This code is taken from a utility for counting lines in all files matching a given spec, in or below a certain folder. It illustrates the technique for recursing into folders quite well.

UINT CCountlinesDlg::GetLineCountForFiles (CString& csStartFolder,
                                           CString& csFileSpec,
                                           BOOL bRecurse)
{
   UINT uRetVal = 0;
   HANDLE hFF = 0;
   WIN32_FIND_DATA wfd;
   int iDotIndex=0;
   CString csPath ;
   CString csFile ;
   CString csSubPath ;
   CString csTgt;
   CString csExtension;
   CString csUpperFileSpec = csFileSpec;

   csUpperFileSpec.MakeUpper();
   m_csOutputDir = csStartFolder ;
   UpdateData (FALSE);

   csTgt = csStartFolder + "\\*.*";

   hFF = FindFirstFile (csTgt,&wfd);

   if (hFF != INVALID_HANDLE_VALUE)
   {
      if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
      {
         if (strcmp (wfd.cFileName, ".") &&
             strcmp (wfd.cFileName, "..") &&
             bRecurse)
         {
            // recurse into the subdir:

            csSubPath = csStartFolder + "\\" + wfd.cFileName;
            uRetVal += GetLineCountForFiles (csSubPath,csFileSpec,bRecurse);
         }
      }
      else
      {
         // Is this one of the target files ?

         csFile = wfd.cFileName;
         iDotIndex = csFile.ReverseFind ('.');
         csExtension = csFile.Right (csFile.GetLength() - (iDotIndex+1));
         csExtension.MakeUpper ();

         if (csExtension == csUpperFileSpec)
         {
            csFile = csStartFolder + "\\" + wfd.cFileName;
            uRetVal += CountLinesIn (csFile);

            m_csOutputFile.Format ("%s : %u", wfd.cFileName, uRetVal);
            UpdateData (FALSE);
         }
      }

      while (FindNextFile (hFF, &wfd))
      {
         if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
         {
            if (strcmp (wfd.cFileName, ".") &&
                strcmp (wfd.cFileName, "..") &&
                bRecurse)
            {
               // recurse into the subdir:

               csSubPath = csStartFolder + "\\" + wfd.cFileName;
               uRetVal += GetLineCountForFiles (csSubPath,csFileSpec,bRecurse);
            }
         }
         else
         {
            // Is this one of the target files ?

            csFile = wfd.cFileName;
            iDotIndex = csFile.ReverseFind ('.');
            csExtension = csFile.Right (csFile.GetLength() - (iDotIndex+1));
            csExtension.MakeUpper();

            if (csExtension == csUpperFileSpec)
            {
               csFile = csStartFolder + "\\" + wfd.cFileName;
               uRetVal += CountLinesIn (csFile);

               m_csOutputFile.Format ("%s : %u", wfd.cFileName, uRetVal);
               UpdateData (FALSE);
            }
         }
      }
   }
   return uRetVal;
}