How to search a file through all subdirectories in Delphi

I implemented this code in Delphi, it will look for the file or the specified name, but it does not look for all subdirectories. How can I do that?

the code:

if FindFirst(filePath,faAnyFile,searchResult)=0 then try repeat lbSearchResult.Items.Append(searchResult.Name); until FindNext(searchResult)<>0 except on e:Exception do ShowMessage(e.Message); end; //try ends FindClose(searchResult); 
+7
source share
5 answers

If you don't need streaming, the easiest way:

 procedure TForm1.AddAllFilesInDir(const Dir: string); var SR: TSearchRec; begin if FindFirst(IncludeTrailingBackslash(Dir) + '*.*', faAnyFile or faDirectory, SR) = 0 then try repeat if (SR.Attr and faDirectory) = 0 then ListBox1.Items.Add(SR.Name) else if (SR.Name <> '.') and (SR.Name <> '..') then AddAllFilesInDir(IncludeTrailingBackslash(Dir) + SR.Name); // recursive call! until FindNext(Sr) <> 0; finally FindClose(SR); end; end; procedure TForm1.Button1Click(Sender: TObject); begin ListBox1.Items.BeginUpdate; AddAllFilesInDir('C:\Users\Andreas Rejbrand\Documents\Aweb'); ListBox1.Items.EndUpdate; end; 
+9
source

With Delphi XE and above, you can take a look at IOUtils.pas:

 TDirectory.GetFiles('C:\', '*.dll', TSearchOption.soAllDirectories); 
+20
source

The easiest way:

 uses DSiWin32; DSiEnumFilesToStringList('c:\somefolder\file.name', 0, ListBox1.Items, true, true); 

DSiWin32 is a free Delphi library.

+4
source

When I need to make tricks as an override of protected methods, I tend to use a general solution to the problem ... I do a class hack.

Here's how to do it using TDirectoryListbox .

In each form you need to use this hacked TDirectoryListbox just add unitTDirectoryListbox_WithHiddenAndSystemFolders to the uses interface, so the form will use the hacked TDirectoryListbox .

Create a file called unitTDirectoryListbox_WithHiddenAndSystemFolders.pas in the proyect folder.

Put this text inside this file (I will explain later what I did):

 unit unitTDirectoryListbox_WithHiddenAndSystemFolders; interface uses Windows ,SysUtils ,Classes ,FileCtrl ; type TDirectoryListbox=class(FileCtrl.TDirectoryListbox) private FPreserveCase:Boolean; FCaseSensitive:Boolean; protected function ReadDirectoryNames(const ParentDirectory:String;DirectoryList:TStringList):Integer; procedure BuildList;override; public constructor Create(AOwner:TComponent);override; destructor Destroy;override; property PreserveCase:Boolean read FPreserveCase; property CaseSensitive:Boolean read FCaseSensitive; end; implementation constructor TDirectoryListbox.Create(AOwner:TComponent); begin inherited Create(AOwner); end; destructor TDirectoryListbox.Destroy; begin inherited Destroy; end; function TDirectoryListbox.ReadDirectoryNames(const ParentDirectory:String;DirectoryList:TStringList):Integer; var TheCount,Status:Integer; SearchRec:TSearchRec; begin TheCount:=0; Status:=FindFirst(IncludeTrailingPathDelimiter(ParentDirectory)+'*.*',faDirectory or faHidden or faSysFile,SearchRec); try while 0=Status do begin if faDirectory=(faDirectory and SearchRec.Attr) then begin if ('.'<>SearchRec.Name) and ('..'<>SearchRec.Name) then begin DirectoryList.Add(SearchRec.Name); Inc(TheCount); end; end; Status:=FindNext(SearchRec); end; finally FindClose(SearchRec); end; ReadDirectoryNames:=TheCount; end; procedure TDirectoryListBox.BuildList; var TempPath: string; DirName: string; IndentLevel, BackSlashPos: Integer; VolFlags: DWORD; I: Integer; Siblings: TStringList; NewSelect: Integer; Root: string; begin try Items.BeginUpdate; Items.Clear; IndentLevel := 0; Root := ExtractFileDrive(Directory)+'\'; GetVolumeInformation(PChar(Root), nil, 0, nil, DWORD(i), VolFlags, nil, 0); FPreserveCase := VolFlags and (FS_CASE_IS_PRESERVED or FS_CASE_SENSITIVE) <> 0; FCaseSensitive := (VolFlags and FS_CASE_SENSITIVE) <> 0; if (Length(Root) >= 2) and (Root[2] = '\') then begin Items.AddObject(Root, OpenedBMP); Inc(IndentLevel); TempPath := Copy(Directory, Length(Root)+1, Length(Directory)); end else TempPath := Directory; if (Length(TempPath) > 0) then begin if AnsiLastChar(TempPath)^ <> '\' then begin BackSlashPos := AnsiPos('\', TempPath); while BackSlashPos <> 0 do begin DirName := Copy(TempPath, 1, BackSlashPos - 1); if IndentLevel = 0 then DirName := DirName + '\'; Delete(TempPath, 1, BackSlashPos); Items.AddObject(DirName, OpenedBMP); Inc(IndentLevel); BackSlashPos := AnsiPos('\', TempPath); end; end; Items.AddObject(TempPath, CurrentBMP); end; NewSelect := Items.Count - 1; Siblings := TStringList.Create; try Siblings.Sorted := True; { read all the dir names into Siblings } ReadDirectoryNames(Directory, Siblings); for i := 0 to Siblings.Count - 1 do Items.AddObject(Siblings[i], ClosedBMP); finally Siblings.Free; end; finally Items.EndUpdate; end; if HandleAllocated then ItemIndex := NewSelect; end; end. 

Now I will explain what I did:

  • By adding unitTDirectoryListbox_WithHiddenAndSystemFolders to the uses interface, I force the form to use the modified component (aka, hacked ).
  • I started by copying a protected method called ReadDirectoryNames (the one that needs to be modified), I will copy it from the FileCtrl unit, and then I will edit this copy on my own device to fix problem (without showing hidden folders or system folders); trick should edit the FindFirst call by adding the or faHidden or faSysFile faDirectory part after faDirectory , also change the SlashSep to IncludeTrailingPathDelimiter (avoid some additional links, etc.) and also perform formatting (indexing, etc.), so I see that this method has been modified.
  • Then I follow the missing things ... like a BuildList , I just simply copy it from unit FileCtrl without any changes (if not copying the hack does not work, as the ReadDirectoryNames call is inside the BuildList ).
  • Then I copy the declaration of FPreserveCase and FCaseSensitive and their property declarations (they are used inside the BuildList method).
  • That is, the now modified TDirectoryListbox will see hidden and system folders

We hope this helps others, so you can simultaneously TDirectoryListbox (original and modified) at the same time (but not in the same form, sorry) in your project, without changing the VCL at all.

PD: Someone who has additional knowledge can add properties for customization, if he should show or not hide and / or system folders as an improvement, he should not be very difficoult, two private logical variables and their corresponding property declaration with read and write methods ... I didn’t do this, because I would like to add not only these two, but also SymLinks, etc. (Search faSymLink on unit SysUtils and see how many there are, work hard to add all of them), sorry for any inconvenience for this.

+1
source

I posted this solution for another question recently:

Delphi: copy files from a folder with a common move. CopyFileEx?

0
source

All Articles