1

SysUtils.FindFirst cannot find all files with extension ~1~ and other strange file extensions, for example: Unit1.dfm.~1~

void __fastcall TForm1::Button1Click(TObject *Sender)
{
  TSearchRec sr;
  int iAttributes = 0;
  StringGrid1->RowCount = 1;
  iAttributes |= faReadOnly;
  iAttributes |= faHidden;
  iAttributes |= faSysFile;
  iAttributes |= faVolumeID;
  iAttributes |= faDirectory;
  iAttributes |= faArchive;
  iAttributes |= faAnyFile;
  StringGrid1->RowCount = 0;
  if (FindFirst(Edit1->Text, iAttributes, sr) == 0)
  {
    do
    {
      if ((sr.Attr & iAttributes) == sr.Attr)
      {
        StringGrid1->RowCount = StringGrid1->RowCount + 1;
        StringGrid1->Cells[1][StringGrid1->RowCount-1] = sr.Name;
        StringGrid1->Cells[2][StringGrid1->RowCount-1] = IntToStr(sr.Size);
      }
    } while (FindNext(sr) == 0);
    FindClose(sr);
  }
}

How to make this code to find all files, with any extension ?

  • 3
    Have you tried removing the attributes check in your code? It looks pretty weird to me. – Uwe Raabe Aug 06 '20 at 10:28
  • 2
    You might also want to rename your check boxes and edit boxes. – Andreas Rejbrand Aug 06 '20 at 12:18
  • The code is straight from the example in some versions of the help for FindFirst. ex. http://docs.embarcadero.com/products/rad_studio/delphiAndcpp2009/HelpUpdate2/EN/html/delphivclwin32/SysUtils_FindFirst.html – Brian Aug 06 '20 at 12:40
  • 1
    @Brian, that doesn't make it fit the requirements. F.i. if faArchive is set, you will only get files with the archive attribute, but not those without. If faArchive is not set, you get all files without the archive attribute, but not those with it. In case you want to check if the file has any of the selected attributes set, you should better check for _!= 0_ instead of _== sr.Attr_ – Uwe Raabe Aug 06 '20 at 12:58
  • @UweRaabe Didn't mean to imply it was good code just noting where it came from. It also doesn't suffice as a mcve as we can't see what is being passed to the function. Could be something as simple as not realizing the history files are in a subdirectory and not in the same directory as the rest of the files. – Brian Aug 06 '20 at 13:05
  • 2
    Show what is being passed to the function - or change the code to use the values directly to have a Minimal, Reproducible Example. – Brian Aug 06 '20 at 13:08
  • @KenWhite that is not entirely true. Per the [documentation](http://docwiki.embarcadero.com/Libraries/en/System.SysUtils.FindFirst): "*The Attr parameter specifies the special files to include **in addition to all normal files**.*". So the search *can* include items that are not covered by the `Attr` parameter alone, so post-filtering is generally required to ensure you get only the items you actually want. See [Understanding FindFirst and FindNext](https://www.tek-tips.com/faqs.cfm?fid=7116) for more details. – Remy Lebeau Aug 06 '20 at 17:14
  • I think the suggestion from @Brian to show what is being passed to the function makes a lot of sense. For example, the content of `Edit->Text` would be one of the key factors that determine the search result. For information, tested the Delphi version of the example from the Embarcadero's documentation (the same page from the link in the earlier comment from @Brian) and could see that it worked (found quite a number of files with `~1~` extension on my machine). http://docs.embarcadero.com/products/rad_studio/delphiAndcpp2009/HelpUpdate2/EN/html/delphivclwin32/SysUtils_FindFirst.html – peter.aryanto Aug 08 '20 at 16:04

1 Answers1

1

The following code will display all items in a directory including the ., .., .~* files - for example in a C++Builder project's history folder :D

I put in the edit box the following string:

C:\Users\david\Documents\Embarcadero\Studio\Projects\FindFirstVCLCpp\__history\*.*

The TMemo contained the following after execution:

. = 0
.. = 0
Unit1.cpp.~1~ = 991
Unit1.cpp.~2~ = 996

The source code for the button handler:

void __fastcall TForm1::Button1Click(TObject *Sender)
{
  TSearchRec sr;
  Memo1->Lines->Clear();
  int iAttributes = 0;
  iAttributes |= faReadOnly;
  iAttributes |= faHidden;
  iAttributes |= faSysFile;
  iAttributes |= faVolumeID;
  iAttributes |= faDirectory;
  iAttributes |= faArchive;
  iAttributes |= faAnyFile;
  if (FindFirst(Edit1->Text, iAttributes, sr) == 0)
  {
    do
    {
      if ((sr.Attr & iAttributes) == sr.Attr)
      {
        Memo1->Lines->Add(
          sr.Name
          + " = "
          + IntToStr(sr.Size)
        );
      }
    } while (FindNext(sr) == 0);
    FindClose(sr);
  }
}
user186876
  • 191
  • 5