scanning a directory

The following code is used to scan a directory or drive for files
There may be some units from the objectpascal toolbox required
If not available, their function should be obvious from the name
To have it doing something useful, substitute the dummy procedures
with real ones.
UNIT DScan;
{$F+}
INTERFACE

USES Dos;

TYPE	PathType	=STRING[64];
TYPE	NameType	=STRING;

TYPE	DChangeProc	=PROCEDURE(NewPath:PathType);
	FMatchProc	=PROCEDURE(N:NameType);
	ECheckProc	=PROCEDURE(VAR S:SearchRec);
	DMatchProc	=FUNCTION(O,N:NameType):BOOLEAN;

PROCEDURE DirectoryScanner(Dir:PathType;Mask:NameType);
PROCEDURE DriveScanner(D:CHAR;Mask:NameType);
PROCEDURE MultiDriveScanner(Dr:STRING;Mask:NameType);

VAR	DirectoryEntryProc,
	DirectoryLeaveProc,
	DirectorySubLeaveProc,
	DirectorySubReentryProc,
	DriveEntryProc,
	DriveExitProc      	:DChangeProc;
	DirectoryNameMatchProc	:DMatchProc;
	FileNameMatchProc	:FMatchProc;
	EntryCheckProc		:ECheckProc;

IMPLEMENTATION

USES OPSTRING;

VAR     NMask	:NameType;
	MName	:NameType;
	MExt	:NameType;

PROCEDURE DCPDummy(S:PathType);
BEGIN
END;
PROCEDURE FMPDummy(N:NameType);
BEGIN
END;
PROCEDURE ECPDummy(VAR S:SearchRec);
BEGIN
END;
FUNCTION DMPDummy(o,N:NameType):BOOLEAN;
BEGIN
 DMPDummy:=TRUE;
END;
FUNCTION MatchName(S:NameType):BOOLEAN;
VAR	N	:NameType;
	M	:NameType;
	E	:NameType;
	D	:NameType;
	match	:BOOLEAN;
BEGIN
 Match:=FALSE;
 IF (NMask='*.*') THEN Match:=TRUE
 ELSE
  BEGIN
   N:=JustName(S);
   E:=JustExtension(S);
   IF (MName='*')or(N=MName) THEN
    BEGIN
     IF (MExt='*')OR(E=MExt) THEN Match:=TRUE;
    END;
  END;	{ else }
 MatchName:=Match;
END;	{ matchname }

PROCEDURE DirectoryScan(Dir:PathType);
VAR	OrgPath,
	NextPath	:STRING;
        S		:SearchRec;

BEGIN
 GetDir(0,OrgPath);
 {$I-}
 ChDir(Dir);
 IF (IOResult<>0) THEN Exit;
 {$I+}
 DirectoryEntryProc(Dir);
 FindFirst('*.*',AnyFile,S);
 WHILE DOSError=0 DO
  BEGIN
   IF (S.Name<>'.') AND
      (S.Name<>'..') AND
      (S.Attr<>VolumeID) THEN
    BEGIN
     IF ((S.Attr and Directory)=Directory) THEN
      BEGIN
       NextPath:=AddBackSlash(Dir)+S.Name;
       IF (DirectoryNameMatchProc(Dir,S.Name)) THEN
	BEGIN
	 DirectorySubLeaveProc(Dir);
	 DirectoryScan(NextPath);
	 DirectorySubReentryProc(Dir);
	END;
      END
     ELSE
      BEGIN
       IF (@EntryCheckProc<>@ECPDummy) THEN EntryCheckProc(s);
       IF (MatchName(S.Name)) THEN
	BEGIN
	 FileNameMatchProc(S.Name);
	END;
      END;
    END;
   FindNext(S);
  END;
 ChDir(OrgPath);
 DirectoryLeaveProc(Dir);
END;

PROCEDURE DirectoryScanner(Dir:PathType;Mask:NameType);
BEGIN
 NMask:=stupcase(Mask);
 MName:=stupcase(JustName(Mask));
 MExt:=stupcase(JustExtension(Mask));
 DirectoryScan(Dir);
END;

PROCEDURE DriveScanner(D:CHAR;Mask:NameType);
VAR OrgPath,NewPath:PathType;
BEGIN
 GetDir(0,OrgPath);
 NewPath:=UpCase(D)+':\';
 DriveEntryProc(NewPath);
 DirectoryScanner(NewPath,Mask);
 ChDir(OrgPath);
 DriveExitProc(NewPath);
END;

PROCEDURE MultiDriveScanner(Dr:STRING;Mask:NameType);
VAR i:BYTE;
BEGIN
 FOR i:=1 TO Length(Dr) DO
  BEGIN
   DriveScanner(Dr[i],Mask);
  END;
END;

BEGIN
 DirectoryEntryProc:=DCPDummy;
 DirectoryLeaveProc:=DCPDummy;
 DirectorySubLeaveProc:=DCPDummy;
 DirectorySubReentryProc:=DCPDummy;
 DirectoryNameMatchProc:=DMPDummy;
 DriveEntryProc:=DCPDummy;
 DriveExitProc:=DCPDummy;
 FileNameMatchProc:=FMPDummy;
 EntryCheckProc:=ECPDummy;
END.


An application

{$F+}
PROGRAM DirectoryScanTest;
USES Dos,OPCrt,OPString,DScan;

VAR Cnt :LONGINT;
    A,B,C:LONGINT; {a:drivesize,b:local dirsize,c:global dirsize}
    at,bt,ct:LONGINT; { trash }
    F:TEXT;
    X:ARRAY[0..20]OF LONGINT;
    Xt:ARRAY[0..20]OF LONGINT;
    xi,xit:BYTE;

PROCEDURE push(i:LONGINT);
BEGIN  
 inc(xi); 
 X[xi]:=i; 
END;
PROCEDURE pusht(i:LONGINT);
BEGIN  
 inc(xit); 
 Xt[xit]:=i; 
END;
FUNCTION Pop:LONGINT;
BEGIN  
 Pop:=X[xi]; 
 dec(xi);
END;
FUNCTION Popt:LONGINT;
BEGIN  
 Popt:=Xt[xit]; 
 dec(xit);
END;

PROCEDURE DriveEntry(P:PathType);
BEGIN
{ Write(chr(13));}
{ Writeln('now ',P);}
 a:=0;b:=0;c:=0;at:=0;bt:=0;ct:=0;
 push(0); pusht(0);
END;
PROCEDURE DriveExit(P:PathType);
VAR Y:SINGLE;
BEGIN
 a:=pop;at:=popt;
 IF (at<>0) THEN y:=100.0*a/at ELSE y:=0;
 Writeln(f,PadCh('Drive '+P,'.',64),Form('##',y),' ',Form('#,###,###,###.',a));
END;

PROCEDURE DirEntryProc(P:PathType);
BEGIN
{ Write(chr(13));
 Write('Scanning ',P,'              ');}
 push(0);pusht(0);
END;

PROCEDURE DirLeaveProc(P:PathType);
VAR Y:SINGLE;
BEGIN
{ Write(chr(13));
 Write('Leaving ',p,'                 ');}
 b:=pop;bt:=popt;
 X[xi]:=X[xi]+b;Xt[xit]:=Xt[xit]+bt;
 IF (bt<>0) THEN y:=100.0*b/bt ELSE y:=0;
 Writeln(f,PadCh('Dir '+p,'.',64),Form('##',y),' ',Form('#,###,###,###.',b));
END;

PROCEDURE DirSubLeaveProc(P:PathType);
BEGIN
END;
PROCEDURE DirSubReentryProc(P:PathType);
BEGIN
END;

PROCEDURE FileMatchProc(N:NameType);
BEGIN
{ Writeln('Processing ',N);}
END;

PROCEDURE EntryCheckingProc(VAR S:SearchRec);
VAR f:FILE;
BEGIN
 inc(cnt);
{ IF (S.Size=0) THEN
  BEGIN
   Writeln(S.Name);
   inc(cnt);
   Assign(f,s.name);
   Erase(f);
  END; }
 Inc(X[xi],S.Size);
 IF (S.Size>=32868) THEN Inc(Xt[xit],S.Size)
 ELSE Inc(Xt[xit],32868);
END;

BEGIN
 cnt:=0;xi:=0;xit:=0;
 Assign(f,'SIZE.TXT');
 ReWrite(f);
 Writeln(f,'Used size determined by size.exe');
 DirectoryEntryProc:=DirEntryProc;
 DirectoryLeaveProc:=DirLeaveProc;
{ FileNameMatchProc:=FileMatchProc;}
 DriveEntryProc:=DriveEntry;
 DriveExitProc:=DriveExit;
 EntryCheckProc:=EntryCheckingProc;
 DirectorySubLeaveProc:=DirSubLeaveProc;
 DirectorySubReentryProc:=DirSubReentryProc;
{ DirectoryScanner('D:\','*.PAS');}
 MultiDriveScanner('CDEFGHIJ','*.*');
 writeln('done - found : ',cnt);
END.

home

last updated: 26.jan.00

Copyright (99,2000) Ing.Büro R.Tschaggelar