Using threads or IFileOperation both involve fairly steep learning curves. Here are a couple of possibilities:
TDirectory method
At Jerry Dodge's prompting I decided to add an example of using TDirectory to
get a list of files and process it in some way, e.g. delete files in the list.
It displays a periodic progress message - see the if i mod 100 = 0 then
statement
in the ProcessFiles
method. Unfortunately I couldn't find a way to show
a periodic message during the list-building stage because AFAIC TDirectory
doesn't expose the necessary hook to do so.
procedure TForm2.ProcessFileList(FileList : TStringList);
var
i : Integer;
S : String;
begin
for i := 0 to FileList.Count - 1 do begin
// do something with FileList[i], e.g. delete it
S := FileList[i];
DeleteFile(S);
// Display progress
if i mod 100 = 0 then // do something to show progress
Caption := Format('Files processed: %d ', [i]);
// OR, you could use i and FileList.Count to set a trackbar % complete
end;
Caption := Format('Processed: %d files', [FileList.Count]);
end;
procedure TForm2.GetFileList(const Path : String; FileList : TStringList);
var
Files : Types.TStringDynArray;
i : Integer;
begin
Files := TDirectory.GetFiles('C:\Temp');
FileList.BeginUpdate;
try
for i:= 0 to Length(Files) - 1 do
FileList.Add(Files[i]);
finally
FileList.EndUpdate;
end;
end;
procedure TForm2.Button1Click(Sender: TObject);
var
FileList : TStringList;
begin
FileList := TStringList.Create;
try
GetFileList('C:\Temp', FileList);
ProcessFileList(FileList);
Memo1.Lines.Text := FileList.Text;
finally
FileList.Free;
end;
end;
It should be evident that this way of doing it is a lot simpler than using the
traditional, Windows-specific method below, at the expense of loss of some flexibility,
and has the advantage of being cross-platform.
IFileOperation method (Windows-specific)
The Windows API has functionality to retrieve and process a list of files e.g. in a directory and there used to be a trivially-simple-to-use wrapper around this, including a progress animation, in the (antique) v.3 of SysTools library from TurboPower S/Ware, but I'm not sure this wrapper ever made it into the later public domain version. On the face if it, it could also be done using the IFileOperation interface but google has yet to conjure a simple example. Note that an SO answer about this contains the comment "this is a very complex API and you do need to read the documentation carefully".
I attempted to do this myself but soon got out of my depth. Remy Lebeau's answer here to the q I posted when I got stuck shows how to do it, but the TDirectory method above seems vastly easier at my skill level.
Traditional (D7) method (Windows-specific)
In my experience, if you are only looking to process a few hundred thousand files, you should be able to do it, displaying progress as you go, by adding the files to a TStringList and then processing that, with code along the following lines:
procedure GetFileList(const Path : String; Recurse : Boolean; FileList : TStringList);
// Beware that the following code is Windows-specific
var
FileCount : Integer;
procedure GetFilesInner(sPath : String);
var
Path,
AFileName,
Ext: String;
Rec: TSearchRec;
Done: Boolean;
begin
Path := IncludeTrailingBackslash(sPath);
if FindFirst(Path + '*.*', faAnyFile, Rec) = 0 then begin
Done := False;
while not Done do begin
if (Rec.Name <> '.') and (Rec.Name <> '..') then begin
AFileName := Path + Rec.Name;
Ext := LowerCase(ExtractFileExt(AFileName));
if not ((Rec.Attr and faDirectory) = faDirectory) then begin
inc(FileCount);
if FileCount mod 100 = 0 then
//show progress in GUI
;
FileList.Add(AFileName)
end
else begin
if Recurse then
GetFilesInner(AFileName);
end;
end;
Done := FindNext(Rec) <> 0;
end;
FindClose(Rec);
end;
end;
begin
FileCount := 0;
FileList.BeginUpdate;
FileList.Sorted := True;
FileList.Duplicates := dupIgnore; // don't add duplicate filenames to the list
GetFilesInner(Path);
FileList.EndUpdate;
end;
procedure TForm1.Button2Click(Sender: TObject);
var
FileList : TStringList;
FileName : String;
i : Integer;
begin
FileList := TStringList.Create;
try
GetFileList('d:\aaad7', True, FileList);
for i := 0 to FileList.Count - 1 do begin
FileName := FileList[i];
// do something with FileName, e.g. delete the file
if i mod 100 = 0 then
// display progess e.g. by
Caption := IntToStr(i);
end;
Memo1.Lines := FileList;
finally
FileList.Free;
end;
end;
The if [...] mod [...] = 0 then
statements are where you can show the two phases' progress howver you want.
Btw, this code was olny intended to get you started. I'm obliged to Jerry Dodge for reminding me that in recent versions of Delphi, there is similar functionality built-in, by way of the TDirectory.GetFiles method so if you are interested in cross-platform and/or accommodate Unicode, you would do better to study the ins and outs of TDirectory and non-Windows-specific routines like TrailingPathDelim.