CFileFind and file extensions

klax33
klax33 used Ask the Experts™
on
I'm trying to write a program to recursivley search the computer and find files with a certain extension and write them to a text file.  This is what I have so far:

#include <afx.h>
#include <iostream>
#include <fstream>

using namespace std;

void Recurse(LPCTSTR pstr)
{
   CFileFind finder;

   // build a string with wildcards
   CString strWildcard(pstr);
   strWildcard += _T("\\*.*");

   // start working for files
   BOOL bWorking = finder.FindFile(strWildcard);

   while (bWorking)
   {
      bWorking = finder.FindNextFile();

      // skip . and .. files; otherwise, we'd
      // recur infinitely!

      if (finder.IsDots())
         continue;

      // if it's a directory, recursively search it

      if (finder.IsDirectory())
      {
         CString str = finder.GetFilePath();
         Recurse(str);
      }

       // now look through the files
       else
       {
            CString file;
            CString search = ".mp3";
            file = (LPCTSTR) finder.GetFilePath();
            cout << search;
                 
            //cout << (LPCTSTR) finder.GetFilePath() << endl;
           
       }
     
   }

   finder.Close();
}

void main()
{
     Recurse(_T("C:"));
}

It does search through the directories correctly, but I don't know how to make it look at each file's extension.  I tried to convert finder.GetFilePath to a string and use string.find but couldn't.  Thanks in advance.
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®

Commented:
Try the following:
CString Ext = finder.GetFileName().Mid(finder.GetFileTitle().GetLength());

Commented:
Full example function:

void Recurse(LPCTSTR pstr)
{
  CFileFind finder;

  // build a string with wildcards
  CString strWildcard(pstr);
  strWildcard += _T("\\*.*");

  // start working for files
  BOOL bWorking = finder.FindFile(strWildcard);

  while (bWorking)
  {
     bWorking = finder.FindNextFile();

     // skip . and .. files; otherwise, we'd
     // recur infinitely!

     if (finder.IsDots())
        continue;

     // if it's a directory, recursively search it

     if (finder.IsDirectory())
     {
        CString str = finder.GetFilePath();
        Recurse(str);
     }

      // now look through the files
      else
      {
           CString file;
           CString search = ".mp3";
           file = (LPCTSTR) finder.GetFilePath();
             CString Ext = finder.GetFileName().Mid(finder.GetFileTitle().GetLength());
           cout << (LPCTSTR)search << endl;
           cout << (LPCTSTR)Ext << endl;
           
      }
     
  }

  finder.Close();
}

Author

Commented:
That sorta works.  It actually just prints out the file extensions over and over.  I modified it a little bit.  But how do I make it so I can change the drive and search term via cin?

For example:
          file = (LPCTSTR) finder.GetFilePath();
          CString Ext = finder.GetFileName().Mid(finder.GetFileTitle().GetLength());
     
            if ( Ext == ".mp3" ) // does not work if ( Ext == search )

and likewise,

void main()
{
        char drive;
        cin >> drive;
     Recurse(_T("drive:"));
}


i also can't use standard output to write to a file

     else
     {
            ofstream output;
            output.open("output.txt", ios::out);
          CString file;
          CString search = ".mp3";
          file = (LPCTSTR) finder.GetFilePath();
          CString Ext = finder.GetFileName().Mid(finder.GetFileTitle().GetLength());
            if ( Ext == ".mp3" )
               output << (LPCTSTR) finder.GetFilePath() << endl;
          //cout << (LPCTSTR)search << endl;
          //cout << (LPCTSTR)Ext << endl;
         
     }

thanks.
OWASP: Avoiding Hacker Tricks

Learn to build secure applications from the mindset of the hacker and avoid being exploited.

Author

Commented:
That sorta works.  It actually just prints out the file extensions over and over.  I modified it a little bit.  But how do I make it so I can change the drive and search term via cin?

For example:
          file = (LPCTSTR) finder.GetFilePath();
          CString Ext = finder.GetFileName().Mid(finder.GetFileTitle().GetLength());
     
            if ( Ext == ".mp3" ) // does not work if ( Ext == search )

and likewise,

void main()
{
        char drive;
        cin >> drive;
     Recurse(_T("drive:"));
}


i also can't use standard output to write to a file

     else
     {
            ofstream output;
            output.open("output.txt", ios::out);
          CString file;
          CString search = ".mp3";
          file = (LPCTSTR) finder.GetFilePath();
          CString Ext = finder.GetFileName().Mid(finder.GetFileTitle().GetLength());
            if ( Ext == ".mp3" )
               output << (LPCTSTR) finder.GetFilePath() << endl;
          //cout << (LPCTSTR)search << endl;
          //cout << (LPCTSTR)Ext << endl;
         
     }

thanks.
Commented:
I recommen you use CompareNoCase instead of Ext == ".mp3" for your comparison.
Also, when you input a string character you have to make sure you have enough memory for the strint
char drive; //This is only a single character

drive needs a string len, and not a single byte char length.
char drive[3];//3 bytes "c:"
You need one character for the drive letter, one character for the full colon, and one byte for the zero byte terminator character.
Here a modified version of your code:

void Recurse(LPCTSTR pstr)
{
  CFileFind finder;

  // build a string with wildcards
  CString strWildcard(pstr);
  strWildcard += _T("\\*.*");

  // start working for files
  BOOL bWorking = finder.FindFile(strWildcard);

  while (bWorking)
  {
     bWorking = finder.FindNextFile();

     // skip . and .. files; otherwise, we'd
     // recur infinitely!

     if (finder.IsDots())
        continue;

     // if it's a directory, recursively search it

     if (finder.IsDirectory())
     {
        CString str = finder.GetFilePath();
        Recurse(str);
     }

      // now look through the files
      else
      {
           CString file;
           CString search = ".mp3";
           file = (LPCTSTR) finder.GetFilePath();
             CString Ext = finder.GetFileName().Mid(finder.GetFileTitle().GetLength());
             if (!Ext.CompareNoCase(".txt")) //If eqaul to ".txt" or ".TXT"
             {
                  cout << "Found ext " << (LPCTSTR)Ext << " on file " << (LPCTSTR)file << endl;
             }
      }
     
  }

  finder.Close();
}

void main_()
{
     TCHAR drive[4];
     cout << "Enter drive letter and full colon, then press enter" << endl;
     cin >> drive;
     cout << endl << "You Entered -> " << drive << endl;
     Recurse(drive);
     cout << endl  << endl;
     system("pause");
}

Author

Commented:
That takes care of the drive letter, now how do I make it so I can change the search extension too?  And output the results to a text file?

Commented:
klax33,
Moreover, this is starting to sound like a homework question, and it's against EE policy for experts to do complete homework questions.  We can help you with specific questions, and point you in the right direction, but we can't do the whole thing.

If you look at the code I've provided, you should be able to figure out how to fetch a different Extension and display the results.

If you have new questions, please post them in a new question, or increase the points to compensate for multiple questions.
And please verify that this is not a homework question.

Author

Commented:
I don't know how exactly to assure you that this is not a homework question other than to simply state that it is not.  I was trying to write something like the Find utility but something I can copy and paste from.  I guess I will just end this question now.  Thank you for all your help.

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial