11

I'm using the Windows API calls FindFirstFile and FindNextFile to search for files matching a certain wildcard string in a directory. For example, I might want to find all XML files in a directory, and so I search using the pattern "*.xml".

I'm running into the problem that if I'm searching for a 3-letter extension, and a file's extension starts with that 3-letter extension, it will get picked up by my search, even if the extension contains more characters after those first 3. For example, if my file is named somelongname.xmlaaaa, this will get picked up by the search for "*.xml". The short name of that file is somelo~1.xml, which matches my wildcard string.

I could do my own wildcard matching to get around this problem, but presumably a Windows API would be able to do this more efficiently than I could, and my code would be simpler. As far as I can tell there isn't a way to force these functions to ignore short names. Is there any API Windows exposes with this functionality?

Chris Vasselli
  • 13,064
  • 4
  • 46
  • 49

2 Answers2

12

Check out FindFirstFileEx - it has a fInfoLevelId parameter that takes a FINDEX_INFO_LEVELS enumeration:

typedef enum _FINDEX_INFO_LEVELS {
  FindExInfoStandard,
  FindExInfoBasic,
  FindExInfoMaxInfoLevel 
} FINDEX_INFO_LEVELS;

FindExInfoBasic

The FindFirstFileEx function does not query the short file name, improving overall enumeration speed. The data is returned in a WIN32_FIND_DATA structure, and the cAlternateFileName member is always a NULL string.

However:

Windows Server 2008, Windows Vista, Windows Server 2003, and Windows XP: This value is not supported until Windows Server 2008 R2 and Windows 7.

Rob Kennedy
  • 161,384
  • 21
  • 275
  • 467
JoeFish
  • 3,009
  • 1
  • 18
  • 23
  • Interesting. I need to support Windows XP, so I probably can't rely on this functionality. Unfortunately, the fact that this got added to this API in Windows 7 probably indicates that it doesn't exist in any other API before then. – Chris Vasselli Nov 09 '11 at 19:40
  • It looks like that's the case. Sorry to have failed you :) And thanks for the edit, @Rob – JoeFish Nov 09 '11 at 19:45
  • It turns out this documentation is very misleading. The search will still find files that match the short name, even if you pass in FindExInfoBasic. It just won't include the short file name in the cAlternateFileName member of the WIN32_FIND_DATA structure. – Chris Vasselli Nov 11 '11 at 01:44
  • 1
    I did however find that there's a Windows function PathMatchSpec that will do the same wildcard matching against a supplied string. So, I was able to add a second step to my searching that verifies that the long name matches the pattern. Thanks for your help @JoeFish! – Chris Vasselli Nov 11 '11 at 01:48
  • @ChrisVasselli Why not post that as an answer? I think it will help future visitors who have the same problem.. – Louis Rhys Sep 26 '12 at 09:32
  • I've found this almost by accident today, just experimenting with different options. Both on mine and coworker's machine this gave us an almost exact x2 speedup. Though this actually decreased our performance by 10% (data was in the cache) - FIND_FIRST_EX_LARGE_FETCH – malkia Aug 27 '14 at 18:48
3

Unfortunately, the documentation JoeFish found in his answer turns out to be a little misleading. The search will still find files that match the short name, even if you pass in FindExInfoBasic. It just won't include the short file name in the cAlternateFileName member of the WIN32_FIND_DATA structure.

I did however find that there's a Windows function PathMatchSpec that will do the same wildcard matching against a supplied string. So, I was able to add a second step to my searching that verifies that the long name matches the pattern. It's even available in Windows XP.

Chris Vasselli
  • 13,064
  • 4
  • 46
  • 49