Как искать различные типы файлов с помощью FindFirst?

В моем приложении я использую следующую процедуру для рекурсивного сканирования любой папки и подпапок, если папка содержит текстовые файлы (*.txt). Я добавляю имя файла в TStringList, определенный в моей процедуре:

procedure FileSearch(const PathName: string; var lstFiles: TStringList);
const
  FileMask = '*.txt';
var
  Rec: TSearchRec;
  Path: string;
begin
  Path := IncludeTrailingBackslash(PathName);
  if FindFirst(Path + FileMask, faAnyFile - faDirectory, Rec) = 0 then
    try
      repeat
        lstFiles.Add(Path + Rec.Name);
      until FindNext(Rec) <> 0;
    finally
      FindClose(Rec);
    end;

  if FindFirst(Path + '*.*', faDirectory, Rec) = 0 then
    try
      repeat
        if ((Rec.Attr and faDirectory) <> 0) and (Rec.Name <> '.') and
          (Rec.Name <> '..') then
          FileSearch(Path + Rec.Name, lstFiles);
      until FindNext(Rec) <> 0;
    finally
      FindClose(Rec);
    end;
end;

Все работает отлично, но я хочу, чтобы иметь возможность искать несколько расширений файлов. Я пробовал модифицировать FileMask для этого, но каждый раз, когда он ничего не возвращает, вероятно, потому что он ищет недопустимое расширение. Я пробовал каждое из следующего без везения: (попробовал один за раз, очевидно, я не писал строки ниже 3 раза в моей процедуре)

FileMask = '*.txt|*.rtf|*.doc';

FileMask = '*.txt;*.rtf;*.doc';

FileMask = '*.txt,*.rtf,*.doc';

Мне неловко спрашивать об этом, но как мне разрешить включение дополнительных расширений файлов в поиск? Я могу сделать это для диалогов Open и Save, почему я не могу отделить расширения здесь?

Спасибо.

Craig.

Ответ 1

Измените свою функцию, чтобы она также приняла список расширений, разделенных точками с запятой или другим разделителем. Затем вы можете проверить наличие каждого найденного расширения файла в этом списке расширений, и если он обнаружит, добавьте его в свой список строк.

Что-то вроде этого должно работать:

procedure FileSearch(const PathName: string; const Extensions: string;
 var lstFiles: TStringList);
const
  FileMask = '*.*';
var
  Rec: TSearchRec;
  Path: string;
begin
  Path := IncludeTrailingBackslash(PathName);
  if FindFirst(Path + FileMask, faAnyFile - faDirectory, Rec) = 0 then
    try
      repeat
        if AnsiPos(ExtractFileExt(Rec.Name), Extensions) > 0 then
          lstFiles.Add(Path + Rec.Name);
      until FindNext(Rec) <> 0;
    finally
      SysUtils.FindClose(Rec);
    end;

  if FindFirst(Path + '*.*', faDirectory, Rec) = 0 then
    try
      repeat
        if ((Rec.Attr and faDirectory) <> 0) and (Rec.Name <> '.') and
          (Rec.Name <> '..') then
          FileSearch(Path + Rec.Name, Extensions, lstFiles);
      until FindNext(Rec) <> 0;
    finally
      FindClose(Rec);
    end;
end;

Пример вызова:

FileSearch('C:\Temp', '.txt;.tmp;.exe;.doc', FileList);

Ответ 2

В Delphi XE7 эта строка кода генерирует (строка 17) ошибку:

finally
  SysUtils.FindClose(Rec);
end;

Чтобы исправить ошибку, я просто удалил SysUtils., чтобы прочитать этот код:

finally
  FindClose(Rec);
end;

Теперь код компилируется отлично. Спасибо за этот очень полезный код и решение.