Solved

Scan directories

Posted on 2001-07-01
35
223 Views
Last Modified: 2010-04-06
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
Comment
Question by:Vincentg
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 15
  • 15
  • 4
  • +1
35 Comments
 
LVL 13

Accepted Solution

by:
Epsylon earned 100 total points
ID: 6242892
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
 
LVL 13

Expert Comment

by:Epsylon
ID: 6242939
Note that 'GetFiles' also scans all subdirectories recursively.
0
 

Author Comment

by:Vincentg
ID: 6242948
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
Technology Partners: 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!

 
LVL 2

Expert Comment

by:bugroger
ID: 6242958
You must set the onClick event from your Button
0
 
LVL 13

Expert Comment

by:Epsylon
ID: 6242959
Did you link the Button1Click event properly?
0
 
LVL 13

Expert Comment

by:Epsylon
ID: 6242963
Hi bugroger, guess we had the same idea  :o)
0
 
LVL 13

Expert Comment

by:Epsylon
ID: 6242969
By the way, you can remove the line

     Application.ProcessMessages;

from the code. It's not necessary.
0
 

Author Comment

by:Vincentg
ID: 6242975
Sorry i didn't link the Button1Click event.. :)
It works 100% now..

many many thanks... :)

Vincent
0
 

Author Comment

by:Vincentg
ID: 6242992
Thank you very much.. !!
0
 

Author Comment

by:Vincentg
ID: 6243200
Thank you very much.. !!
0
 

Author Comment

by:Vincentg
ID: 6243664
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
 
LVL 13

Expert Comment

by:Epsylon
ID: 6246488
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
 

Author Comment

by:Vincentg
ID: 6249873
Thanks a lot for your help.. :)

0
 

Author Comment

by:Vincentg
ID: 6250075
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
 
LVL 13

Expert Comment

by:Epsylon
ID: 6250132
As far as I can see it does already scan subdirs...
0
 

Author Comment

by:Vincentg
ID: 6250626
Hi Epsylon,

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

0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 6251483
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
 
LVL 13

Expert Comment

by:Epsylon
ID: 6251607
Vincent, doesn't it scan subdirs or do you get an error?
0
 
LVL 13

Expert Comment

by:Epsylon
ID: 6251820
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
 

Author Comment

by:Vincentg
ID: 6252140
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
 

Author Comment

by:Vincentg
ID: 6252233
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
 

Author Comment

by:Vincentg
ID: 6252244
Ofcource with *.html it wil not find the subdirs :)
Is there a workaround for this??
0
 

Author Comment

by:Vincentg
ID: 6252365
Ofcource with *.html it wil not find the subdirs :)
Is there a workaround for this??
0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 6252667
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
 

Author Comment

by:Vincentg
ID: 6252710
Ofcource with *.html it wil not find the subdirs :)
Is there a workaround for this??
0
 
LVL 13

Expert Comment

by:Epsylon
ID: 6252712
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
 
LVL 27

Expert Comment

by:kretzschmar
ID: 6252720
?? thats really strange
0
 
LVL 13

Expert Comment

by:Epsylon
ID: 6252748
EE is very, VERY buggy, believe me.....
0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 6253718
now you got me, eps :-))

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

congrates for place 4 in the top 15
0
 
LVL 13

Expert Comment

by:Epsylon
ID: 6253739
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
 

Author Comment

by:Vincentg
ID: 6253742
Thanks :) I'm going to bed now, so i see the result in the morning.. a good begin of the day ;)
0
 
LVL 13

Expert Comment

by:Epsylon
ID: 6253860
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
 
LVL 13

Expert Comment

by:Epsylon
ID: 6253864
Now you can use:

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

etc.
0
 

Author Comment

by:Vincentg
ID: 6257240
Epsylon, you are the best :) many thanks.
0
 
LVL 13

Expert Comment

by:Epsylon
ID: 6260184
You're welcome  :o)
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!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

A lot of questions regard threads in Delphi.   One of the more specific questions is how to show progress of the thread.   Updating a progressbar from inside a thread is a mistake. A solution to this would be to send a synchronized message to the…
Creating an auto free TStringList The TStringList is a basic and frequently used object in Delphi. On many occasions, you may want to create a temporary list, process some items in the list and be done with the list. In such cases, you have to…
With Secure Portal Encryption, the recipient is sent a link to their email address directing them to the email laundry delivery page. From there, the recipient will be required to enter a user name and password to enter the page. Once the recipient …

732 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question