Tutorial: Write your own FindFiles tool

How to use FindFirst and FindNext with recursion, for adding filenames and paths to a stringlist

How to create a list of the files in a folder and its subfolders

In the following short tutorial, I'll show you the basics for writing your own "Find Files" tool.
 
The procedure FindFiles(FilesList, StartDir, FileMask) locates files in a given folder and its subfolders. The files correspond to a filemask that you specify.

Parameter FilesList is a stringlist to which the full paths of the files will be added.
 
In parameter StartDir you pass the starting directory (folder), including the disk drive. If you want to search an entire disk, you specify the root directory of that disk, such as C:\ or A:\

In parameter FileMask you pass the name of the file to find, or a file mask with wildcards (using * and ?). Examples:

FindFiles(FilesList, 'c:\', 'letter01.doc');
FindFiles(FilesList, 'c:\', '*.dpr');
FindFiles(FilesList, 'd:\projects', 'test??.dpr');

If you want to try this procedure, add the following components to a form:

  • two Edits (one for the starting directory, one for the mask)
  • a Button
  • a TLabel
  • a ListBox

The source code of FindFiles

In FindFiles we use recursion: the procedure calls itself, in order to find the files that are located in subdirectories.


procedure FindFiles(FilesList: TStringList;
  StartDir, FileMask: string);
var
  SR: TSearchRec;

  DirList: TStringList;
  IsFound: Boolean;
  i: integer;
begin
  if StartDir[Length(StartDir)] <> '\' then
    StartDir := StartDir + '\';

  // Build a list of the files in directory StartDir
  // Do not include the directories!

  IsFound :=
    FindFirst(StartDir+FileMask, faAnyFile-faDirectory, SR) = 0;
  while IsFound do begin
    FilesList.Add(StartDir + SR.Name);
    IsFound := FindNext(SR) = 0;
  end;
  FindClose(SR);

  // Build a list of subdirectories
  DirList := TStringList.Create;
  IsFound := FindFirst(StartDir+'*.*', faAnyFile, SR) = 0;
  while IsFound do begin
    if ((SR.Attr and faDirectory) <> 0) and
         (SR.Name[1] <> '.') then
      DirList.Add(StartDir + SR.Name);
    IsFound := FindNext(SR) = 0;
  end;
  FindClose(SR);

  // Scan the list of subdirectories recursively
  for i := 0 to DirList.Count-1 do
    FindFiles(DirList[i], FileMask);

  DirList.Free;
end;

How to use FindFiles?

Before calling FindFiles, you create a stringlist to which FindFiles will add the full paths of the files that are found. The contents of the stringlist can be shown in a listbox, saved to disk, whatever...  Finally, you have to free this stringlist.


procedure TForm1.ButtonFindClick(Sender: TObject);
var
  FilesList: TStringList;
begin
  FilesList := TStringList.Create;
  try
    FindFiles(FilesList, EditStartDir.Text, EditFileMask.Text);
    ListBox1.Items.Assign(FilesList);
    LabelCount.Caption := 'Files found: ' + IntToStr(FilesList.Count);
    // Other processing with the list of files...
    // ...
  finally
    FilesList.Free;
  end;
end;

 

Share this article!

Follow us!

Find more helpful articles:

Comments

Oct
15

hello,
On my computer (Windows XP Sp2 and Delphi 7.0 Enterprise),
the line 84 of code : FindFiles(DirList[i], FileMask); don't works !
and give me this message : [Error] Unit1.pas(84): Incompatible types: 'TStringList' and 'String'
Please, tell me why !
Thanks
Pierre (from France)

By berpi berpi