Link to home
Start Free TrialLog in
Avatar of jpetter
jpetter

asked on

How to Recursively Search Drive for Specific File Types

Hi,
I'm writing a utility program that will allow LAN Managers to remotely backup files on remote PC's as a preperatory step to the user either moving or receiving a new PC. Actually the backup is not really a backup, but a copy to a folder of their choice. The main functionality behind this piece is based upon some code I found I think on CodeGuru, or CodeProject. Anyway, it worked fine when I passed the method the folder to start searching in, along with the file type to search for. However, a common complaint was that the LAN Managers would need to run this multiple times to capture the different files. For instance, they may have .docs in ..\My Documents, and .xls files in \CurrentProjects. They would have to then check the "doc" extenstion check box and the populate the start search text box and run the program, and then check the "xls" check box and populate its start search text box. Well, one approach would have been to place a text box to start searching from next to each check box. However, I was trying to search from the root of the drive, and compare each file's extension to that being sought, and if there was a match, a copy would follow. Needless to say, I have had some major issues trying to get it to work.

I'm posting the most current version of what DOESN'T work. If any has some ideas regarding how I can recursively find file types starting from the root, I would appreciate it.

Thanks,
Jeff


BOOL CFileBackupDlg::CopyExtension(CString csRoot, CString csDest, CString csCriteria)
{
      BOOL                        bRet = FALSE;
      BOOL                        bRes = FALSE;
      CString                        csPathMask;
      CString                        csFullPath;
      CString                        csNewFullPath;
      CString                        csNewPath;
      CString                        csMsg;
      CString                        strFirst;
      CString                        strSecond;
      CString                        csBuf;
      CString                        csSub;
      CString                        csToMatch;
      DWORD                        dwRet = 0;
      WIN32_FIND_DATA            fd;
      HANDLE                        hFind;
      int                              nchar = 0;

      ////////////////////////////////////////////////////////////////
      csRoot += _T("\\");
      csDest += _T("\\");

      csNewPath = csDest + csCriteria.Mid(2);
      CreateDirectory (csNewPath, NULL);
      csPathMask = csRoot + _T("*.*");

      hFind = FindFirstFile (csPathMask, &fd);
      if (hFind == INVALID_HANDLE_VALUE)
      {
            MessageBox ("The file criteria did not return any matches. Ensure the folder selection is correct and try again.",
                              "File Find Error", MB_OK);
            return FALSE;
      }
      else
      {
            // strip the extension from the incoming criteria
            nchar = csCriteria.Find (_T("."));
            if (nchar != -1)
                  csToMatch = csCriteria.Mid (nchar + 1);
            // see if the file found is one we're looking for
            csBuf = fd.cFileName;
            //strip the extension from the file we found
            nchar = csBuf.Find (_T("."));
            if (nchar != -1)
            {
                  csSub = csBuf.Mid (nchar + 1);
                  if (csSub.CompareNoCase (csToMatch) == 0)
                  {
                        csFullPath = csRoot + fd.cFileName;
                        csNewFullPath = csDest + fd.cFileName;
                        CopyFile (csFullPath, csNewFullPath, FALSE);
                        strFirst = GetCRC (csFullPath, dwRet);
                        strSecond = GetCRC (csNewFullPath, dwRet);
                        if (strFirst != strSecond)
                        MessageBox ("File copy integrity check failed! The file may be corrupt or missing!",
                                          csFullPath, MB_OK);

                        csMsg = "Copying: " + csFullPath;
                        SetDlgItemText (IDC_STATUS, csMsg);

                  }
            }
            while (hFind && FindNextFile (hFind, &fd))
            {
                  //need to add checking to check for matching extensions

                  nchar = csCriteria.Find (_T("."));
                  if (nchar != -1)
                        csToMatch = csCriteria.Mid (nchar + 1);
                  // see if the file found is one we're looking for
                  csBuf = fd.cFileName;
                  //strip the extension from the file we found
                  nchar = csBuf.Find (_T("."));
                  if (nchar != -1)
                  {
                        csSub = csBuf.Mid (nchar + 1);
                        if (csSub.CompareNoCase (csToMatch) == 0)
                        {
                              csFullPath = csRoot + fd.cFileName;
                              csNewFullPath = csDest + fd.cFileName;
                              // see if it's a file or a folder
                              if (!(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
                              {
                                    bRes = CopyFile (csFullPath, csNewFullPath, FALSE);
                                    strFirst = GetCRC (csFullPath, dwRet);
                                    strSecond = GetCRC (csNewFullPath, dwRet);
                                    if (strFirst != strSecond)
                                          MessageBox ("File copy integrity check failed! The file may be corrupt or missing!",
                                                csFullPath, MB_OK);
                                    if (!bRes)
                                    {
                                          bRet = FALSE;
                                    }
                                    csMsg = "Copying: " + csFullPath;
                                    SetDlgItemText (IDC_STATUS, csMsg);
                              }
                              else // probably a directory
                              {
                                    if ((_tcscmp (fd.cFileName, _T(".")) != 0) && 
                                          (_tcscmp (fd.cFileName, _T("..")) != 0))
                                    {
                        
                                          if (!CopyFolder (csFullPath, csNewFullPath, csCriteria))
                                          {
                                                bRet = FALSE;
                                          }
                                    }
                              }
                        }

                  }
                  else // probably a directory
                  {
                        if ((_tcscmp (fd.cFileName, _T(".")) != 0) && 
                                    (_tcscmp (fd.cFileName, _T("..")) != 0))
                        {
                              if (!CopyFolder (csFullPath, csNewFullPath, csCriteria))
                              {
                                    bRet = FALSE;
                              }
                        }
                  }

            }
      }
      SetDlgItemText (IDC_STATUS, "");
      FindClose (hFind);
      return bRet;
                        
}

Avatar of jkr
jkr
Flag of Germany image

Could you be a bit more specific about what exactly is not working?
I would create a string that contains all extensions you are interested in:
string extensions = ".doc.xls.pdf.txt";

Create this when the user clicks the "OK" button, after all the extensions that need to be backed up are selected. Then, in your look that searches for the files, after you extract the extension of the current file (stored in the variable currentExtension), do something like this:

if (extensions.find(currentExtension) != npos)
{
    // file needs to be backed up
}
else
{
    // file does not need to be backed up - you may not need this else branch
}
Avatar of jpetter
jpetter

ASKER

Sure, it does iterate through the files in the root, and through the debugger (BTW, MS VC++ v 6) I can see it comparing the extenstions to the search criteria. When the current file is a folder, and I try to "step into" the recursive call, I can't for some reason. However, it bombs out at the beginning of the method where I check to see if I have a valid file handle returned from FindFirstFile. I wish I was more competent with the debugger, because I would like to see what is being passed for the values. Normally I have no problem, but when it's called recursively I can't see it.

Thanks,
Jeff
Looks like I misunderstood your question :-)

Can you please provide the CopyFolder() code as well.
SOLUTION
Avatar of Karl Heinz Kremer
Karl Heinz Kremer
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of jpetter

ASKER

jkr &  khkremer,

You guys have given me some great help. Let me play around with this a second.

One problem, as both of you caught. I modified my CopyFolder function to end up with CopyExtension, but never changed the call when I go to call it recursively. And that is probably why I don't append the csFullPath, because the variable names are different.

If this turns out to be the solution, what a total tool I'll feel like. How careless.

Thanks, and I'll get right back.
Avatar of jpetter

ASKER

Well, those eye openers that caught my oversights did allow me to get further. Now I just have to rework the function a little so that it doesn't die when I hit an empty folder.

Thanks,
Jeff
Where does it die in an empty folder?
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of jpetter

ASKER

I can't thank all of you enough for all of your help. The support I've received on this has been terrific!

I'll split up the points, and wish I had more to go around.

Thanks again,
Jeff