We help IT Professionals succeed at work.

Check out our new AWS podcast with Certified Expert, Phil Phillips! Listen to "How to Execute a Seamless AWS Migration" on EE or on your favorite podcast platform. Listen Now

x

Locating files

Gal
Gal asked
on
Medium Priority
394 Views
Last Modified: 2010-04-04
Hi,
I'm new to Delphi, and still using Delphi 2.0 (wow!),
I'm looking for a function to let me locate a file in the user's HD. FileSearch and FileExists both take parameters of directories, but there's no way to  look in subdirs as well.
since I don't know where or whether the app that created the files I need to locate has been installed, I need to look for them. anybody got an idea? this is quite urgent!
Comment
Watch Question

Commented:
Unlock this solution and get a sample of our free trial.
(No credit card required)
UNLOCK SOLUTION

Commented:
This is one of the many ways.
It searches using regular expression in any UNC directory, and puts all matching filenames in a TStrings list:

function FindFiles( sDir, sMask: string; rgsFiles: TStrings; bRecursively: Boolean ): Integer;
var
  SR: TSearchRec;
begin
  Result := 0;
  if not Assigned( rgsFiles ) then Exit;
  if sDir[ Length( sDir )] <> '\' then AppendStr( sDir, '\' ); // fix dir
  if FindFirst( sDir + sMask, faAnyFile, SR ) = 0 then repeat
    if ( SR.Attr and faDirectory ) <> faDirectory then rgsFiles.Add( sDir+SR.Name );
  until FindNext( SR ) <> 0;
  FindClose( SR );
  // recursive part...
  if bRecursively then begin
    if FindFirst( sDir + '*.*', faAnyFile, SR ) = 0 then repeat
      if (( SR.Attr and faDirectory ) = faDirectory ) and ( SR.Name[1] <> '.' )
      then FindFiles( sDir+SR.Name+'\', sMask, rgsFiles, bRecursively );
    until FindNext( SR ) <> 0;
    FindClose( SR );
  end;
  Result := rgsFiles.Count;
end;

Usage:
  FindFiles( 'c:\', '*.txt', ListBox1.Items, True );
or
  MyStrings := TStringList.Create;
  cLog := FindFiles( '\\server\logs\', '*.log', MyStrings, False );
etc...

I hope this will work in D2!

/// John
 

Commented:
Whooah BoRiS! You're fast!
/// John

Commented:
Appendix:
  the faAnyFile declared in Delphi might not be enough, hence:

const
  faNormal     = $00000080;
  faTemporary  = $00000100;
  faCompressed = $00000800;
  faAnyFileEx  = faReadOnly or faHidden or faSysFile or faVolumeID or faDirectory or faArchive or faNormal or faTemporary or faCompressed;

Just replace all occurances of faAnyFile with faAnyFileEx.
Without this, all files will NOT be found!

/// John
Gal

Author

Commented:
Thanks, BoRiS, erajoj.

I will try it out this evening and let you know how it went.
Thanks!

(BTW, BoRiS, I understand you're almost a neighbour - Tel-Aviv? I'm in Herzeliya. (Israel).

Commented:
Gal

No sorry...  I stay in South Africa...

Later
BoRiS
Gal

Author

Commented:
OK, erajoj, I implemented that piece of code you gave me, but I still don't really get it - I mean, I went through the logic, and it does work (I tested it too, of course). what I don't get yet is how to be able to get the File's full name (UNC) to a string-type var to be able to figure out its path, (extractFileDir), its date (FileAge) etc., to figure out if I need to replace it with a new one, append to it, and so on.
Thanks
Gal

Commented:
Hi,
There are of course, as always, several ways to attack this problem. The files in the list are in full name format, provided the sDir parameter is a full UNC directory name.

To get a path out of the list you do as usual:
  sPath := MyList[ 0 ]; // for example
To get the file time stamp, you just call FileGetDate:
  FileDate := FileGetDate( sPath );
To convert the date to TDateTime format:
  dtFile := FileDateToDateTime( FileDate );

Another way to do this is to modify the search function:

type
  PFileData = ^TFileData;
  TFileData = record
    Path, Name: string;
    Time : TDateTime;
    Size, Attr : Integer;
  end;

  ...

function NewFindFiles( sDir, sMask: string; rgFileData: TList; bRecursively: Boolean ): Integer;
var
  SR: TSearchRec;
  pfd: PFileData;
begin
  Result := 0;
  if not Assigned( rgsFiles ) then Exit;
  if sDir[ Length( sDir )] <> '\' then AppendStr( sDir, '\' ); // fix dir
  if FindFirst( sDir + sMask, faAnyFile, SR ) = 0 then repeat
    if ( SR.Attr and faDirectory ) <> faDirectory then begin
      New( pfd );
      rgFileData.Add( pfd );
      with pfd^ do begin
        Name := SR.Name;
        Path := sDir;
        Size := SR.Size;
        Attr := SR.Attr;
        Time := FileDateToDateTime( SR.Time );
      end;
    end;
  until FindNext( SR ) <> 0;
  FindClose( SR );
  // recursive part...
  if bRecursively then begin
    if FindFirst( sDir + '*.*', faAnyFile, SR ) = 0 then repeat
      if (( SR.Attr and faDirectory ) = faDirectory ) and ( SR.Name[1] <> '.' )
      then FindFiles( sDir+SR.Name+'\', sMask, rgsFiles, bRecursively );
    until FindNext( SR ) <> 0;
    FindClose( SR );
  end;
  Result := rgsFiles.Count;
end;


Then, to use it:
 
var
  myfiledata: PFileData;
  MyFileDataList: TList;
  ...
 
  if ( NewFindFiles( 'c:\', '*.txt', MyFileDataList, True ) > 0 ) then begin
    myfiledata := MyFileDataList[ 0 ];
    with myfiledata^ do begin
      if ( ( Date-Time ) > 7 ) then ... /// more than a week old!
      FullFilename := Path + Name;
    end;
  end;

You just have to clean up after you. MyFileDataList.Clear or MyFileDataList.Free is NOT enough. You still have data on your heap, so:

  for iIndex := 0 to MyFileDataList.Count - 1 do
    Dispose( PFileData( MyFileDataList[ iIndex ] ) );
  MyFileDataList.Free;

Thats about it.

/// John
Gal

Author

Commented:
Hi erajoj.
I just noticed that they routed the point for this question you answered for me to BoRiS. I don't know why, but I guess it's because something I did or didn't do?
Anyway, the points clearly belong to you, so, if there's a way to reroute them, please let me know so I can do that
Sorry for the inconvenience.
Gal.

Commented:
Hi Gal.
Don't be sorry!
The points are not important at all if you're content with the answer!
BoRiS gave you a good answer and deserves the points.

/// John
Gal

Author

Commented:
Well, thanks any way to both of you.
This session really got me going with my program here.
Thanks a lot and keep up the good work.

Gal.

Unlock the solution to this question.
Thanks for using Experts Exchange.

Please provide your email to receive a sample view!

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

OR

Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.