• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 233
  • Last Modified:

Scan directories

Hello,

I need some help, what i like to do is this :

Scan 1 or 2 dirs for files and check when they are modified and then remember the 10 last modified files. The 10 filenames have to be put in a var so i can put them in a HTML file with hyperlinks.

Does somebody have some code that can do this?

Thanks a lot.

Vincent
0
Vincentg
Asked:
Vincentg
  • 15
  • 15
  • 4
  • +1
1 Solution
 
EpsylonCommented:
Try this:


unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls;

type
  PFile = ^TFile;
  TFile = packed record
            filename: String;
            filedate: TDateTime;
          end;

  TForm1 = class(TForm)
    Button1: TButton;
    ListBox1: TListBox;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
    filelist: TList;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure GetFiles(const DirStr : string; filelist: TList);
var
  DirInfo: TSearchRec;
  r : Integer;
  fr: PFile;
begin
  ChDir(DirStr);
  r := FindFirst('*.*', FaAnyfile, DirInfo);
  while r = 0 do  begin
    Application.ProcessMessages;
      if (DirInfo.Name <> '.') and (DirInfo.Name <> '..') then
      begin
        New(fr);
        fr.filename := DirStr + '\' + DirInfo.Name;
        fr.filedate := FileDateToDateTime(DirInfo.Time);
        filelist.Add(fr);
        if (DirInfo.Attr and faDirectory) <> 0 then
          GetFiles(DirStr + '\' + DirInfo.Name, filelist);
      end;
    r := FindNext(DirInfo);
  end;
  FindClose(DirInfo);
end;

function SortFileList(Item1, Item2: Pointer): Integer;
begin
  if TFile(Item1^).filedate < TFile(Item2^).filedate then
    Result := 1
  else if TFile(Item1^).filedate > TFile(Item2^).filedate then
    Result := -1
  else
    Result := 0;
end;

procedure TForm1.Button1Click(Sender: TObject);
var i: Integer;
begin
  filelist := TList.Create;

// scan directories
  GetFiles('c:\dir1', filelist);
  GetFiles('c:\dir2', filelist);

// sort the files (newer files first)
  filelist.Sort(SortFileList);

// clear all items except first 10
  while filelist.Count > 10 do
  begin
    Dispose(filelist[filelist.Count - 1]);
    filelist.Delete(filelist.Count - 1);
  end;

// show the files + dates
  for i := 0 to filelist.Count - 1 do
    ListBox1.Items.Add(DateTimeToStr(TFile(filelist[i]^).filedate) + ' ' + TFile(filelist[i]^).filename);

// clear all (remaining) items
  while filelist.Count > 0 do
  begin
    Dispose(filelist[filelist.Count - 1]);
    filelist.Delete(filelist.Count - 1);
  end;
 
  filelist.Free;
end;

end.
0
 
EpsylonCommented:
Note that 'GetFiles' also scans all subdirectories recursively.
0
 
VincentgAuthor Commented:
Hello Epsylon,

I copy/paste your code but nothing happens, not even a error message. :(
Do i something wrong or is there a 'little mistake' in the code?

Vincent
0
Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
bugrogerCommented:
You must set the onClick event from your Button
0
 
EpsylonCommented:
Did you link the Button1Click event properly?
0
 
EpsylonCommented:
Hi bugroger, guess we had the same idea  :o)
0
 
EpsylonCommented:
By the way, you can remove the line

     Application.ProcessMessages;

from the code. It's not necessary.
0
 
VincentgAuthor Commented:
Sorry i didn't link the Button1Click event.. :)
It works 100% now..

many many thanks... :)

Vincent
0
 
VincentgAuthor Commented:
Thank you very much.. !!
0
 
VincentgAuthor Commented:
Thank you very much.. !!
0
 
VincentgAuthor Commented:
There is one little problem :(
In the list are also directories, is it possible to delete them and only put files in the list??

Vincent
0
 
EpsylonCommented:
Hmmm... I didn't receive a notification message for your last comment. I already had the idea I missed some other notifications, but now I am sure: E-E is devolving  :o(


This should prevent directories form being added to the list:

procedure GetFiles(const DirStr : string; filelist: TList);
var
  DirInfo: TSearchRec;
  r : Integer;
  fr: PFile;
begin
  ChDir(DirStr);
  r := FindFirst('*.*', FaAnyfile, DirInfo);
  while r = 0 do
  begin
    if (DirInfo.Name <> '.') and (DirInfo.Name <> '..') then
    begin
      if (DirInfo.Attr and faDirectory) = 0 then
      begin
        New(fr);
        fr.filename := DirStr + '\' + DirInfo.Name;
        fr.filedate := FileDateToDateTime(DirInfo.Time);
        filelist.Add(fr);
      end
      else
        GetFiles(DirStr + '\' + DirInfo.Name, filelist);
    end;
    r := FindNext(DirInfo);
  end;
  FindClose(DirInfo);
end;
0
 
VincentgAuthor Commented:
Thanks a lot for your help.. :)

0
 
VincentgAuthor Commented:
Hello Epsylon,

I searched EE for this one but can't find anything.
I would like to scan the subdirs also.. Can you help??
It's no problem to make it a question, you only have to say so..

Thanks again..

Vincent
0
 
EpsylonCommented:
As far as I can see it does already scan subdirs...
0
 
VincentgAuthor Commented:
Hi Epsylon,

Not here, if i give c:\ it only checks c:\ and no subdirs..

0
 
kretzschmarCommented:
guessing the recursion want to change the directory to

c:\\anyotherdirname

which is not possible

just use this changes

procedure GetFiles(const DirStr : string; filelist: TList);
var
 DirInfo: TSearchRec;
 r : Integer;
 fr: PFile;
begin
 ChDir(DirStr);
 r := FindFirst('*.*', FaAnyfile, DirInfo);
 while r = 0 do
 begin
   if (DirInfo.Name <> '.') and (DirInfo.Name <> '..') then
   begin
     if (DirInfo.Attr and faDirectory) = 0 then
     begin
       New(fr);
       fr.filename := DirStr + '\' + DirInfo.Name;
       fr.filedate := FileDateToDateTime(DirInfo.Time);
       filelist.Add(fr);
     end
     else
       if DirStr[length(DirStr)] <> '\' then   //here is the change
         GetFiles(DirStr + '\' + DirInfo.Name, filelist)
       else
         GetFiles(DirStr + DirInfo.Name, filelist);
   end;
   r := FindNext(DirInfo);
 end;
 FindClose(DirInfo);
end;

meikl ;-)
0
 
EpsylonCommented:
Vincent, doesn't it scan subdirs or do you get an error?
0
 
EpsylonCommented:
I fixed the \ problem and the scan now skips system directories (_Restore, System Volume Information, RECYCLER, etc,) which will interrupt the scan with an access denied error.


procedure GetFiles(DirStr : string; filelist: TList);
var
  DirInfo: TSearchRec;
  r : Integer;
  fr: PFile;
begin
  if DirStr[Length(DirStr)] <> '\' then
    DirStr := DirStr + '\';
  ChDir(DirStr);
  r := FindFirst('*.*', FaAnyfile, DirInfo);
  while r = 0 do
  begin
    if (DirInfo.Name <> '.') and (DirInfo.Name <> '..') then
    begin
      if (DirInfo.Attr and faDirectory) = 0 then
      begin
        New(fr);
        fr.filename := DirStr + DirInfo.Name;
        fr.filedate := FileDateToDateTime(DirInfo.Time);
        filelist.Add(fr);
      end
      else
        if (DirInfo.Attr and faSysFile) = 0 then
          GetFiles(DirStr + DirInfo.Name, filelist);
    end;
    r := FindNext(DirInfo);
  end;
  FindClose(DirInfo);
end;
0
 
VincentgAuthor Commented:
I now know what the problem is. If i scan for *.html it seems that the subdirs are not scaned. It only find files in the given dir, if i change it to *.* it works 100%.. very strange :(

0
 
VincentgAuthor Commented:
I now know what the problem is. If i scan for *.html it seems that the subdirs are not scaned. It only find files in the given dir, if i change it to *.* it works 100%.. very strange :(

0
 
VincentgAuthor Commented:
Ofcource with *.html it wil not find the subdirs :)
Is there a workaround for this??
0
 
VincentgAuthor Commented:
Ofcource with *.html it wil not find the subdirs :)
Is there a workaround for this??
0
 
kretzschmarCommented:
i use this sceleton

procedure FindFile(PathFileName : string; IncludeSubDirs : Boolean);

     var
       srec : TSearchRec;
       FHandle : integer;
       Path, FileName : String;
     begin
       Path := ExtractFilePath(PathFileName);
       FileName := ExtractFileName(PathFileName);
       // CurrentDirectory
       if findfirst(PathFileName,faanyfile,srec) = 0 then
       begin
         repeat
           If Not(srec.attr and fadirectory > 0) then
           begin

                  // FileFound do something with it

           end;
         Until findnext(srec) <> 0;
       end;
       FindClose(SRec);
       { SubDirectories }
       If IncludeSubDirs then
       begin
         if FindFirst(Path+'*.*',FaAnyFile,Srec) = 0 then
         begin
           repeat
             // StartRecursion
             if not(Srec.Name[1] = '.') and (srec.attr and fadirectory > 0)then
               FindFile(Path + Srec.Name + '\' + FileName,IncludeSubDirs)
           Until findnext(srec) <> 0;
         end;
         FindClose(SRec);
       end;
     end;

meikl ;-)
0
 
VincentgAuthor Commented:
Ofcource with *.html it wil not find the subdirs :)
Is there a workaround for this??
0
 
EpsylonCommented:
That's strange... When Meikl posts comment, I get a notification but not when Vincent posts a comment.

Very odd...


Vincent, I will work it out later...
0
 
kretzschmarCommented:
?? thats really strange
0
 
EpsylonCommented:
EE is very, VERY buggy, believe me.....
0
 
kretzschmarCommented:
now you got me, eps :-))

but be sure i don't let you runaway :-) (hopefully)

congrates for place 4 in the top 15
0
 
EpsylonCommented:
Thank you, Meikl. Don't worry, you'll have your 4th place back soon when you catch Raymond   :o)

Vincent, I'm going to work on it now.
0
 
VincentgAuthor Commented:
Thanks :) I'm going to bed now, so i see the result in the morning.. a good begin of the day ;)
0
 
EpsylonCommented:
procedure GetFiles(DirStr: string; filelist: TList);
var DirInfo: TSearchRec;
    r : Integer;
    fr: PFile;
    pattern: String;
begin
  pattern := ExtractFileName(DirStr);
  if Pos('*', pattern) > 0 then
    DirStr := ExtractFilePath(DirStr)
  else
    pattern := '*.*';
  if DirStr[Length(DirStr)] <> '\' then
    DirStr := DirStr + '\';
  if SetCurrentDir((DirStr)) then
  begin
    r := FindFirst(pattern, FaAnyfile, DirInfo);
    while r = 0 do
    begin
      if (DirInfo.Attr and faDirectory) = 0 then
      begin
        New(fr);
        fr.filename := DirStr + DirInfo.Name;
        fr.filedate := FileDateToDateTime(DirInfo.Time);
        filelist.Add(fr);
      end;
      r := FindNext(DirInfo);
    end;
    FindClose(DirInfo);
    r := FindFirst('*.*', FaAnyfile, DirInfo);
    while r = 0 do
    begin
      if (DirInfo.Attr and faDirectory) <> 0 then
        if (DirInfo.Name <> '.') and (DirInfo.Name <> '..') then
// comment out the next line to exclude system directories
//          if (DirInfo.Attr and faSysFile) = 0 then
            GetFiles(DirStr + DirInfo.Name + '\' + pattern, filelist);
      r := FindNext(DirInfo);
    end;
    FindClose(DirInfo);
  end;
end;
0
 
EpsylonCommented:
Now you can use:

c:
c:\
c:\*.*
c:\*.htm
c:\*.*
c:\dir1
c:\dir1\
c:\dir1\*.pas

etc.
0
 
VincentgAuthor Commented:
Epsylon, you are the best :) many thanks.
0
 
EpsylonCommented:
You're welcome  :o)
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

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