2

When I try to call CFileFind.FindFile(_T("D://Folder//*.txt")), the method returns true when the only file is "foobar.txta".

However, I don't want the file foobar.txta to be included the find result. How do I make it that way? Probably by using other method or another if ? I'm a newbie in C++ :))

Note: This issue does not seem to happen if the exension is less than 3, for example if filter is "*.tx" and file is "foobar.txt" the method still (correctly) return false. Also, the issue seems to be reported here but seems like I need to pay to see the solution

Louis Rhys
  • 34,517
  • 56
  • 153
  • 221

4 Answers4

1

It seems to be a bug in CFindFile (or in the Win32 API FindFirstFile). But you can determine the real extension later by calling CFindFile::GetFileName:

CFindFile finder;
BOOL bWorking = finder.FindFile(L"*.txt");

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

    if (finder.GetFileName().Right(finder.GetFileName().ReverseFind(L'.')) != L".txt")
        // the file extension is not .txt
}
user1610015
  • 6,561
  • 2
  • 15
  • 18
  • Nope, not a bug. MSDN is explicit: "The search includes the long and short file names." – MSalters Sep 25 '12 at 08:17
  • Thank you, but the above is just example, in reality the application takes any wildcard.. Any idea how to make the solution more general? – Louis Rhys Sep 25 '12 at 08:18
  • @LouisRhys If the extension part of the wildcard doesn't use any wildcard characters, you could compare that extension with the extension of each found file. If the extension does contain wildcard characters, I don't think there's an easy answer. You'd have to do actual pattern-matching of the extensions (i.e. basically what CFindFile does, only correctly). – user1610015 Sep 25 '12 at 08:58
  • @user1610015 I found that [`PathMatchSpec`](http://msdn.microsoft.com/en-us/library/windows/desktop/bb773727%28v=vs.85%29.aspx) did the trick. If you include that in the answer I'll accept it – Louis Rhys Sep 26 '12 at 02:17
0

This is a common Windows behavior for backwards compatibility. Files without an "8.3" name may have an short synonym. I.e. "foobar.txta" is also called "foobar.txt". If you indeed meant just *.txt, you'll have to manually check the results. Those results will use the long name, so you can discard the *.txt? files

You can do the manual check afterwards with PathMatchSpec("foobar.txta", "*.txt"). Note that despite the name, this function is really only suited for extension matching. Don't expect anything but *.ext to work.

See also Is there an alternative to the Windows FindFirstFile/FindNextFile API that doesn't search short file names?

Community
  • 1
  • 1
MSalters
  • 173,980
  • 10
  • 155
  • 350
0

I hope this would work.

WIN32_FIND_DATA ffd;
    CStringList strFileNameList;
    CStringList strFileMask;
    int iCntFiles = 0;
    HANDLE          hFind     = INVALID_HANDLE_VALUE;
 CONST CHAR cszFileName[] = "test.txt";

 strFileMask = strFileName.Left(strFileName.Find(cszFileName)) + "*.txt";
    hFind          = FindFirstFile(strFileMask.GetBufferSetLength(strFileMask.GetLength()), &ffd);

    if (INVALID_HANDLE_VALUE == hFind) 
    {
        return;
    } 
    else
    {
        // List all the other files in the directory.
        strFileNameList.AddTail(ffd.cFileName);
        iCntFiles++;
        while (FindNextFile(hFind, &ffd) != 0) 
        {
            strFileNameList.AddTail(ffd.cFileName);
            iCntFiles++;
        }
}

Now from all the text file save in CStringList Now it can be extract.

jiten
  • 5,128
  • 4
  • 44
  • 73
0

As the other answerers have noted, the apparent bug is because a Windows file have a 8.3 alias, causing "foobar.txta" to be detected as "foobar.txt". To make sure that a file found by CFileFind indeed match the wildcard pattern, use 'PathMatchSpec' to validate the file returned by finder.GetNextFile(). PathMatchSpec seems not to be affected by the 8.3 alias.

Louis Rhys
  • 34,517
  • 56
  • 153
  • 221