2

I am currently stuck with this bit of code that only gives me the very first occurrence of a specific file in the top most folder of a given directory that I am trying to find. I want to modify this to list/return all occurrences of the file.

{ Credits to (I believe) TLama for some/most of this excerpt of code. }

{ Looks for specific file }
var
  filelocation: string;
  { ^ Global Variable }

function FindFile(RootPath: string; FileName: string): string;
var
  FindRec: TFindRec;
  FilePath: string;
begin
  Log(Format('', [RootPath, FileName]));

  if FindFirst(RootPath + '\*', FindRec) then
  begin
    try
      repeat
        if (FindRec.Name <> '.') and (FindRec.Name <> '..') then
        begin
          FilePath := RootPath + '\' + FindRec.Name;
          if FindRec.Attributes and FILE_ATTRIBUTE_DIRECTORY <> 0 then
          begin
            Log(FilePath);
            Result := FindFile(FilePath, FileName);
            if Result <> '' then Exit;
          end
            else
          if CompareText(FindRec.Name, FileName) = 0 then
          begin 
            { list each \userdata\(numbers here) here that include 240.json within them }
            Log(Format('User' + {user} + ' owns (Game Here) on Steam.', [FilePath]));

            Result := FilePath;
            filelocation := FilePath
          end;                             
        end;
      until not FindNext(FindRec);
    finally
      FindClose(FindRec);
    end;
  end
    else
  begin
    Log(Format('Failed to list %s', [RootPath]));
    MsgBox('You do not own (Game Here). Please purchase and install it from Steam.',
           mbError, MB_OK);
    Exit;
  end;
end;
Tim Lewis
  • 27,813
  • 13
  • 73
  • 102

1 Answers1

1

The following code collects all found files into TStringList:

procedure FindFile(RootPath: string; FileName: string; FileLocations: TStringList);
var
  FindRec: TFindRec;
  FilePath: string;
begin
  Log(Format('Looking for %s in %s', [FileName, RootPath]));

  if FindFirst(RootPath + '\*', FindRec) then
  begin
    try
      repeat
        if (FindRec.Name <> '.') and (FindRec.Name <> '..') then
        begin
          FilePath := RootPath + '\' + FindRec.Name;
          if FindRec.Attributes and FILE_ATTRIBUTE_DIRECTORY <> 0 then
          begin
            FindFile(FilePath, FileName, FileLocations);
          end
            else
          if CompareText(FindRec.Name, FileName) = 0 then
          begin 
            Log(Format('Found %s', [FilePath]));

            { Here you can do additional check (for file contents) }

            FileLocations.Add(FilePath);

            Break;
          end;                             
        end;
      until not FindNext(FindRec);
    finally
      FindClose(FindRec);
    end;
  end
    else
  begin
    Log(Format('Failed to list %s', [RootPath]));
  end;
end;

You can use it like:

var
  FileLocations: TStringList;
begin
  FileLocations := TStringList.Create();
  FindFile('C:\some\path', '240.json', FileLocations);
end;

And then process the FileLocations as you need:

for I := 0 to FileLocations.Count - 1 do
begin
  FileName := FileLocations[I];
  { Process FileName }
end;

Though if you do not need to process the files multiple times, you can as well process them directly in FindFile and you do not need to collect the names into a list.

Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992