在 Delphi 中从文件搜索中排除特定文件夹

o2gm4chl  于 2023-06-22  发布在  其他
关注(0)|答案(2)|浏览(172)

我使用下面的代码从目录和子目录的文件搜索
如何修改此代码以从文件搜索中排除任何特定的文件夹
如从驱动器C:中排除Windows目录

procedure FindFilePattern(root:String;pattern:String);
var
  SR:TSearchRec;
begin
  root:=IncludeTrailingPathDelimiter(root);
  if FindFirst(root+'*.*',faDirectory or faHidden ,SR) = 0 then
  begin
      repeat
          Application.ProcessMessages;
          if ((SR.Attr and faDirectory) = faDirectory ) and (pos('.',SR.Name)=0) then
             FindFilePattern(root+SR.Name,pattern)
          else
          begin
           if pos(pattern,SR.Name)>0 then Form1.ListBox1.Items.Add(Root+SR.Name);
          end;
      until FindNext(SR)<>0;
      FindClose(SR);
  end;
end;

我找了很多关于它,但没有找到任何合适的解决方案

arknldoa

arknldoa1#

对你的问题有一些评论…
排除某些目录的简单方法是传递要从搜索中排除的文件夹列表。
在这种情况下,您可以添加一个新参数,其中包含您不想浏览的目录列表(TStrings)。header看起来像这样:

procedure FindFilePattern(root:String; pattern:String; ExcludedFolders:TStrings);

调用应该是这样的:

var
  EF:TStrings;
begin
  EF := TStringList.Create;
  EF.Add('c:\Windows');
  FindFilePattern(edtRoot.Text, edtPattern.Text, EF);
  FreeAndNil(EF);

您必须修改过程以检测这些元素,而不是浏览它:

procedure FindFilePattern(root:String; pattern:String; ExcludedFolders:TStrings);
var
  SR:TSearchRec;
begin
  root:=IncludeTrailingPathDelimiter(root);
  if FindFirst(root+'*.*',faDirectory or faHidden ,SR) = 0 then
  begin
      repeat
          Form1.memo1.Lines.Add(Root+SR.Name);
          Application.ProcessMessages;
          if ((SR.Attr and faDirectory) = faDirectory ) and (pos('.',SR.Name)=0) then
          begin
            // find if the finded element is in the ExcludedList (i = -1 ==> not finded) 
            var i:integer := ExcludedFolders.IndexOf(Root+SR.Name);
            // it's a directory and not finded in excluded => continue... 
            if ((SR.Attr and faDirectory) = faDirectory) and (i=-1) then
              FindFilePattern(root+SR.Name, pattern, ExcludedFolders);
          end
          else
          begin
           if pos(pattern,SR.Name)>0 then
            Form1.ListBox1.Items.Add(Root+SR.Name);
          end;
      until FindNext(SR)<>0;
      FindClose(SR);
  end;
end;

另一个注解是关于这一行的,这一行用于返回结果。正确的做法是使用输出参数,而不是从函数内部引用接口的元素。

Form1.ListBox1.Items.Add(Root+SR.Name);

为找到的元素列表添加新参数:

procedure FindFilePattern(root:String; pattern:String; ExcludedFolders:TStrings; Finded:TStrings);

调用将是这样的:

var
  EF, List:TStrings;
begin
  EF := TStringList.Create;     // excluded dirs
  List := TStringList.Create;   // Finded elements
  try
    EF.Add('c:\Windows');
    EF.Add('c:\temp');
    FindFilePattern(edtRoot.Text, edtPattern.Text, EF, List);
    Form1.ListBox1.Items.AddStrings(List);
  finally
    FreeAndNil(EF);
    FreeAndNil(List);
  end;

程序是这样的:

procedure FindFilePattern(root:String; pattern:String; ExcludedFolders:TStrings; Finded:TStrings);
var
  SR:TSearchRec;
begin
  root:=IncludeTrailingPathDelimiter(root);
  if FindFirst(root+'*.*',faDirectory or faHidden ,SR) = 0 then
  begin
      repeat
          // Form1.memo1.Lines.Add(Root+SR.Name);
          Application.ProcessMessages;
          if ((SR.Attr and faDirectory) = faDirectory ) and (pos('.',SR.Name)=0) then
          begin
            var i:integer := ExcludedFolders.IndexOf(Root+SR.Name);
            if ((SR.Attr and faDirectory) = faDirectory) and (ExcludedFolders.IndexOf(Root+SR.Name)=-1) then
              FindFilePattern(root+SR.Name, pattern, ExcludedFolders, Finded);
          end
          else
          begin
           if pos(pattern,SR.Name)>0 then
            // Form1.ListBox1.Items.Add(Root+SR.Name);
            Finded.Add(Root+SR.Name);
          end;
      until FindNext(SR)<>0;
      FindClose(SR);
  end;
end;
8dtrkrch

8dtrkrch2#

从System.IOUtils单元中使用TDirectory.GetDirectories。

program Project1;

{$APPTYPE CONSOLE}

{$R *.res}
 
uses
  System.SysUtils, System.IOUtils;
const
  IGNORE_DIR = 'System';
var
  c: string;
begin
  try
    for c in TDirectory.GetDirectories('C:\Windows', '*.*',
       function(const Path: string; const SearchRec: TSearchRec): Boolean
       begin
         Result := not SameFilename(SearchRec.Name, IGNORE_DIR);
                                   end) do
    writeln(c);
    readln(c);

  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.

相关问题