views:

1110

answers:

5

I asked about finding in subdirs with criteria. First answer was use FindFirstFileEx(). It seems the function is no good for this purpose or I'm using it wrong.

So can someone explain how I would go about searching in a folder, and all it's subfolders for files that match (to give some sample criteria) .doc;.txt;*.wri; and are newer than 2009-01-01?

Please give a specific code example for those criteria so I know how to use it.

If it isn't possible, is there an alternative for doing this not-at-all-obscure task??? I am becoming quite baffled that so far there aren't well known/obvious tools/ways to do this.

A: 

I think you use FindFirstFile to find all files and ignore the ones whose WIN32_FIND_DATA values don't match your search criteria.

ChrisW
right, that's pretty much exactly what I already do with the findfirst function. So I guess I won't achieve anything by using a different function. I was hoping for something that was designed to do the filtering for me (therefore would be more efficient). I guess I'll stick. thanks anyway :)
MrVimes
I don't think this is right.. FindFirstFile returns when it finds the first file that matches your critera I think..
krebstar
this is a bit difficult to explain. if I specify criteria in the first param (such as "c:\asampledir\*.doc") then it won't find directories, therefore it won't allow the surrounding code to search in subdirectories, since the surrounding code waits for the file to be a dir and then runs recursively
MrVimes
That's not correct, if you have a directory name "c:\asampledir\sampledocdir.doc\somefile.doc", and you search for "c:\asampledir\*.doc" it will match the directory.
scottm
+2  A: 

From MSDN:

If you refer to the code fragment in that page:

#include <windows.h>
#include <tchar.h>
#include <stdio.h>

void _tmain(int argc, TCHAR *argv[])
{
   WIN32_FIND_DATA FindFileData;
   HANDLE hFind;

   if( argc != 2 )
   {
      _tprintf(TEXT("Usage: %s [target_file]\n"), argv[0]);
      return;
   }

   _tprintf (TEXT("Target file is %s\n"), argv[1]);
   hFind = FindFirstFileEx(argv[1], FindExInfoStandard, &FindFileData,
             FindExSearchNameMatch, NULL, 0);
   if (hFind == INVALID_HANDLE_VALUE) 
   {
      printf ("FindFirstFileEx failed (%d)\n", GetLastError());
      return;
   } 
   else 
   {
      _tprintf (TEXT("The first file found is %s\n"), 
                FindFileData.cFileName);
      FindClose(hFind);
   }
}

You'll see that you can call FindFirstFileEx, where argv[1] is a string (LPCSTR) pattern to look for, and &FindFileData is a data structure that contains file info of the found data.. hFind is the handle you use on subsequent calls with FindNextFile.. I think you can also add more search parameters by using the fourth and sixth parameter to FindFirstFileEx.

Good luck!

EDIT: BTW, I think you can check a file or dir's attributes by using GetFileAttributes() .. Just pass the filename found in FileFindData.. (filename can refer to a file's name or a directory name I think)

EDIT: MrVimes, here's what you could do (in pseudocode)

find the first file (match with *)

  • Check the file find data if it is ".", ".." (these are not really directories or files)
    • if check passed, check file find data if it has the attributes you are looking for (i.e. check filename, file attributes, even file creation time can be checked in the file find data, and what not) and do whatever with it
      • if check passed, do whatever you need to do with the file
    • if check failed, either call findnextfile or end, up to you

Something like that..

krebstar
A: 

Well you could use it to search for *.doc, *.txt and *.wri by passing those values as the name to search for:

FindFirstFileEx("*.doc", FindExInfoStandard, &fileData, FindExSearchNameMatch, NULL, 0);

To search by date is a little more complicated, but not overly so:

SYSTEMTIME createTime;
SYSTEMTIME searchDate;
FILETIME compareTime;
HANDLE searchHandle;

searchDate.wYear = 2009;
searchDate.wMonth= 1;
searchDate.wDay = 1;

SystemTimeToFileTime(searchDate, &compareTime);

searchHandle FindFirstFileEx("*", FindExInfoStandard, &fileData, FindExSearchNameMatch, NULL, 0);

if(searchHandle != INVALID_HANDLE_VALUE)
{
While(searchHandle != ERROR_NO_MORE_FILES)
{
FileTimeToSystemTime(fileData.ftCreationTime, &createTime);

if((ULARGE_INTEGER)compareTime < (ULARGE_INTEGER)createTime)
  printf("%s matches date criteria", fileData.cFileName);

FindNextFile(searchHandle, &fileData);
}
}
scottm
A: 

You need to do two searches. The first is just to find the subdirs, and you do that without any file spec. The second search for the files uses the file spec.

Mark Ransom
A: 

Why don't you read the dozens of complete samples in MSDN (W. SDK, KB, docs, etc) ???!!!!