Johan
Johan

Reputation: 76577

count number of subdirectories of a given path

I need to do some searching in the filesystem and would like to present a progress indication.
A rough approximation of that is the number of directories traversed.

function GetSubDirCount(Path : String): integer;
var
  Index : Integer;
  Temp : String;
  SearchRec : TSearchRec;
begin
  Result:= 0;
  Temp:= Path;

  if Path[Length(Path)] <> SysUtils.PathDelim then begin
    Path:= Path + SysUtils.PathDelim;
  end;
  Path:= Path + '*.';

  Index:= FindFirst(Path, faDirectory, SearchRec);

  while Index = 0 do begin
    if (SearchRec.Name = '.') or (SearchRec.Name = '..') then begin
      Index:= FindNext(SearchRec);
      Continue;
    end;

    Inc(Result);
    Result:= Result + GetSubDirCount(Temp + SysUtils.PathDelim + SearchRec.Name);
    Index:= FindNext(SearchRec);
  end;

  FindClose(SearchRec);
end;

I currently use the above code, is there a faster way?
I'm only interested in the count.
If there's a really fast way to get the number of files as well that would be a bonus.

Upvotes: 1

Views: 1326

Answers (3)

Jan Doggen
Jan Doggen

Reputation: 9096

@Johan Since the Windows code takes up most time, I suggest you apply the fixes suggested by other respondents, and update your code to use threads if your feel comfortable with that:

  • As soon as you retrieve a subdirectory put add it to a (thread safe) list

  • Have a thread look at that list and spawn worker threads do to the actual file processing per directory

  • Update your progress all the time: number of dirs found/handled. This will be a bit wobbly in the beginning, but at least you can start working while Windows is still 'finding'

The 'usual' warnings apply:

  • don't make your number of threads too large

  • if your file processing creates new files make sure your find routines don't choke on the new output files

Upvotes: 0

Chris Thornton
Chris Thornton

Reputation: 15817

Minor improvement: use const in the parameter declaration. ex:

function GetSubDirCount(const Path : String): integer;

As Rob points out, this will not work as Path is modified in the body. I would still use this approach however, and NOT modify path in the body. I'd have a local string var "Suffix", modify that (add optional pathdelim, and '*.'), and pass both to FindFirst:

FindFirst(Path+Suffix, faDirectory, SearchRec);

Upvotes: 0

Uwe Raabe
Uwe Raabe

Reputation: 47714

As you are not specifying the Delphi version you are using, I suggest the corresponding methods from IOUtils - namely TDirectory.GetDirectories and TDirectory.GetFiles as they are available in recent Delphi versions.

Update: It is probably not the fastest way to count the number of directories and files, but if the files shall be iterated later anyway, one could as well use the result of these functions for the iteration.

Upvotes: 4

Related Questions