Go Premium for a chance to win a PS4. Enter to Win

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 819
  • Last Modified:

Find a file in a Delphi application

Maybe this exists already so I do not have to code it by myself
I look for a function that will receive a filename, says myfile.txt as argument 1, a directory says mydir as argument 2 and the function will return the first occurrence (full name) of that file somewhere under the mydir structure ...
Thanks
0
LeTay
Asked:
LeTay
  • 3
  • 2
  • 2
  • +1
1 Solution
 
aikimarkCommented:
I don't think there's an intrinsic Delphi function to do this.  Normally, I would expect to see a solution that involves recursing through the directory tree, stopping when it finds the desired file.

Do you need to do this a lot or is this a one shot search?
How important is performance?
0
 
lopemCommented:
Try this example code using FileSearch:

//Searching in the current directory and beyond
var
  myFile       : TextFile;
  fileName     : string;
  fullFilePath : string;
  dir1, dir2   : string;

begin
  // The file we will be searching for
  fileName := 'Test.txt';

  // Write to a text file in the current directory
  AssignFile(myFile, fileName);
  ReWrite(myFile);
  Write(myFile, 'Hello World');
  CloseFile(myFile);

  // Write to a text file to another directory
  AssignFile(myFile, 'C:\Program Files\'+fileName);
  ReWrite(myFile);
  Write(myFile, 'Hello World');
  CloseFile(myFile);

  // Define two directories where we want to search for the file
  dir1 := 'C:\No such directory';
  dir2 := 'C:\Program Files';

  // Search for the file
  fullFilePath := FileSearch(fileName, dir1+';'+dir2);

  // If we search now, we will find it in the current directory
  if fullFilePath = ''
  then ShowMessage(fileName+' not found')
  else ShowMessage(fullFilePath+' found OK');

  // Now delete Test.txt from the current directory and retry
  DeleteFile(fileName);

  // If we search now, we will find it in one of the search dirs
  fullFilePath := FileSearch(fileName, dir1+';'+dir2);
  if fullFilePath = ''
  then ShowMessage(fileName+' not found')
  else ShowMessage(fullFilePath+' found OK');
end;
0
 
Sinisa VukCommented:
this is how to find file in subfolders using Findfirst, FindNext functions:
function FindInFolder(sFolder, sFile: String; bUseSubfolders: Boolean): String;
var
  sr: TSearchRec;
  i: Integer;
  sDatFile: String;
begin
  //finf file in current folder
  Result := '';
  sFolder := IncludeTrailingPathDelimiter(sFolder);
  if SysUtils.FindFirst(sFolder + sFile, faAnyFile - faDirectory, sr) = 0 then
  begin
    Result := sFolder + sr.Name;
    SysUtils.FindClose(sr);
    Exit;
  end;

  //not found .... search in subfolders
  if bUseSubfolders then
  begin
    //find first subfolder
    if SysUtils.FindFirst(sFolder + '*.*', faDirectory, sr) = 0 then
    begin
      try
        repeat
          if ((sr.Attr and faDirectory) <> 0) and (sr.Name <> '.') and (sr.Name <> '..') then //is real folder?
          begin
            //recursive call!
            Result := FindInFolder(sFolder + sr.Name, sFile, bUseSubfolders);
            if Length(Result) > 0 then Break; //found it ... escape
          end;
        until SysUtils.FindNext(sr) <> 0;  //...next subfolder
      finally
        SysUtils.FindClose(sr);
      end;
    end;
  end;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  s: String;
begin
  s := FindInFolder('D:\Work', 'file.zip', True);
  if s <> '' then ShowMessage('Found: ' + s);
end;

Open in new window


Parameters to application you can get using ParamCount and ParamStr:
if ParamCount>=2 then  //more than one params
begin
  s := FindInFolder(ParamStr(2), ParamStr(1), True);
  if s <> '' then ShowMessage('Found: ' + s);
end;

Open in new window

0
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 
lopemCommented:
Hi, Sinisa, your code takes care of subdirectories also?
0
 
Sinisa VukCommented:
yes, if you put True (as third parameter) like in example.
0
 
lopemCommented:
cool! Nice code
0
 
aikimarkCommented:
Another approach is to shell out a Dir /s /b highlevelpath\filename > somepath\dirlist.txt command and then read the contents of the dirlist.txt file.  You can even use wildcard characters in the file name.

I think there might have been a sysutils library or JEDI unit that had reasonably fast performance searching for files in a directory tree.

If you are using XE7 (maybe 6), you might try the parallel For loop to search the directory tree.
0
 
LeTayAuthor Commented:
Finally I wrote this, inspired by Sinisa who gets the points
I had already a recursive function to analyse a directory structure for other purposes...

function BTFileSearch(FileName,Dir:string):string;
var
 F:TSearchRec;
begin
 Result := '';
 FileName := LowerCase(FileName);
 if (FindFirst(Dir + '\*.*',faAnyFile,F) = 0)
  then repeat
   if (F.Name = '.') or (F.Name = '..') then Continue;
   if ((faDirectory and F.Attr) <> 0)
     then begin
       Result := BTFileSearch(FileName,Dir + '\' + F.Name);
       if (Length(Result) <> 0)
         then begin
           FindClose(F);
           Exit;
         end;
     end
     else begin
       if (LowerCase(F.Name) = FileName)
         then begin
           Result := Dir + '\' + FileName;
           FindClose(F);
           Exit;
         end;
     end;
  until (FindNext(F) <> 0);
 FindClose(F);
end;
0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

  • 3
  • 2
  • 2
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now