Главная страница | назад





Article #23175: Finding all files (or files of a certain type) in a given directory

Question:
Given a directory name, how do I find all files in that directory (or files of a specific type, such as *.jpg)? How to I optionally search through all subdirectories?

Answer:
You can use FindFirst and FindNext functions in SysUtils. Here is an example:

{  procedure GetFiles -
    Parameters:
      ADirectory: string; // A directory to search for files
      Files: TStringList; // The list of files to put the result in
      SubFolders: Boolean; // If True, it searches subfolders too }
	  
procedure GetFiles(const ADirectory: string; Files: TStringList; SubFolders: Boolean);
	// Helper function to remove any slashes or add them if needed
  function SlashSep(const Path, S: string): string;
  begin
    if AnsiLastChar(Path)^ <> '\' then
      Result := Path + '\' + S
    else
      Result := Path + S;
  end;
var
  SearchRec: TSearchRec;
  nStatus: Integer;
begin
  // First find all the files in the current directory 
  // You could put something else instead of *.*, such as *.jpeg or *.gif
  // to find only files of those types.
  nStatus := FindFirst(PChar(SlashSep(ADirectory, '*.*')),  0, SearchRec);
  while nStatus = 0 do
  begin
    Files.Add(SlashSep(ADirectory, SearchRec.Name));
    nStatus := FindNext(SearchRec);
  end;
  FindClose(SearchRec);
  // Next look for subfolders and search them if required to do so
  if SubFolders then
  begin
    nStatus := FindFirst(PChar(SlashSep(ADirectory, '*.*')), faDirectory,
      SearchRec);
    while nStatus = 0 do
    begin
      // If it is a directory, then use recursion
      if ((SearchRec.Attr and faDirectory) <> 0) then
      begin
        if ( (SearchRec.Name <> '.') and (SearchRec.Name <> '..') )  then
          GetFiles(SlashSep(ADirectory, SearchRec.Name), Files, SubFolders);
      end;
      nStatus := FindNext(SearchRec)
    end; 
    FindClose(SearchRec);
  end;
end;

Click here to download the source and sample program from Code Central.

NOTE: Delphi 4's FindClose function has a bug in it and can make this code run in an infinite loop. You will need to change the FindClose function in SysUtils.pas to look like this:


procedure FindClose(var F: TSearchRec);
begin
  if F.FindHandle <> INVALID_HANDLE_VALUE then
  begin
    Windows.FindClose(F.FindHandle);
    F.FindHandle := INVALID_HANDLE_VALUE;
  end;
end;

Last Modified: 07-NOV-00