Delphi: FileSystem Searching

The windows api comes with several functions to search through files in a computer’s filesystem such as FindFirstFile, FindNextFile, … The RTL library in Delphi encapsulates these functions in 3 easy to use functions. These are FindFirst, FindNext and FindClose. Unlike what you may be used to from the win32 api, these functions return 0 not if something went wrong, but if they were successful. You have to pass the function a mask for the files, this consists out of a filemask to search in the current directory or a filemask including a folderpath. An example would be “c:\*”, this would return all files or folders in c:\ depending on what flags you pass to the FindFirst function. Note that the functions are not recursive, so they will only return the content of a folder and not it’s subfolders. The second parameter of the FindFirst function specifies flags that tell the functions what it is searching for. A few flags are faNormal, faHidden, faSysFile, faDirectory, … These can also be combined to select several types of files/directories. The following example shows you how to loop through all files and directories in the c:\ folder:

program FindTest;

{$APPTYPE CONSOLE}

uses
  SysUtils;

var
  sRec: TSearchRec;
begin
  if FindFirst('c:*', faNormal or faDirectory, sRec) = 0 then
  begin
    repeat
      WriteLn(sRec.Name + ' - ' + IntToStr(sRec.Size));
    until FindNext(sRec) <> 0;
    FindClose(sRec);
  end;
  ReadLn; // Prevent window from closing
end.

If you would for example change your mask to “c:\*.txt”, it would only return the txt files.

Some of you will also want to be able to recurse this, this can easily be achieved by setting it up in a recursive algoritm:

program FindTest;

{$APPTYPE CONSOLE}

uses
  SysUtils;

procedure RecurseFileSystem(const Folder, Mask: string);
var
  sRec: TSearchRec;
  t: string;
begin
  t := IncludeTrailingPathDelimiter(Folder);
  if FindFirst(t + Mask, faNormal or faDirectory, sRec) = 0 then
  begin
    repeat
      if ((sRec.Attr and faDirectory) <> 0) and (sRec.Name <> '.') and
        (sRec.Name <> '..') then
        RecurseFileSystem(t + sRec.Name, Mask)
      else
        WriteLn(t + sRec.Name + ' - ' + IntToStr(sRec.Size));
    until FindNext(sRec) <> 0;
    FindClose(sRec);
  end;
end;

begin
  RecurseFileSystem('c:', '*');
  ReadLn; // Prevent window from closing
end.

This example will loop through the entire filesystem on the c drive and show you all of the regular files including their path and size.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.