EDirTree implements recursive scanning for files using a simple, yet powerfull interface.
EDirTree now uses forward slashes and FindClose if conditional Linux (see syseq.inc) exists.
TYPE ReportProc = PROCEDURE (Path:PathStr;Search:SearchRec); FileProc = PROCEDURE(P:PathStr;Search:SearchRec); DirProc = PROCEDURE(P:PathStr); DetectProc = FUNCTION(Search:SearchRec;P:PathStr):BOOLEAN;These proceduretypes accept one or two parameters.
The DirProc has only one parameter since it operates on a directory. The DetectProc type is a function, and the return value indicates if the file should be added to the tree (TRUE) or not (FALSE).
TYPE FilAttr = BYTE;
This type is meant to type the attributes for FindFirst and FindNext. A remnant of the units Modula-2 origin where it is a SET type.
Files aren't included in this picture. Imagine every directory having a linked list of files in the direction perpendicular to the screen.
Fileptr = ^FilesRec; FilesRec = RECORD Next : FilePtr; {next file in this directory} DirE : SearchRec; { Unit DOS, record for findfirst} END; DirTreePoint = ^DirTreeRecord; DirTreeRecord = RECORD NextDir, {next directory on this level} SubDirs : DirTreePoint; {subdirectories (Lower than this level)} Name : PathStr; {Name of directory} Files : FilePtr; {see above} END;
VAR DirsToo : BOOLEAN; Are matching directories reported to the main module? See ScanTree and FileScan.
The variables below are updated by FileScan, SearchForFiles(not FoundDirs) and BuildTree (Only FoundDirs), after each scan. ClearStat resets them to zero, ClearStat is also run on startup.
VAR FoundCount : WORD; Number of files found TotalBytes : LONGINT; Total bytes in files found. See also ClusterSize FoundDirs : WORD; Directories found ( . and .. are ignored)
The LONGINT ClusterSize can be used to influence TotalBytes, , TotalBytes can be rounded up to account for clustersize (or inode size, or however the filesystem calls it). If you specify ClusterSize=0, no rounding will be performed.
ClusterSize : LONGINT; Clustersize used for rounding, default 0= no rounding
Declaration
PROCEDURE SetFAttr (Attr:FilAttr);
Description
Sets attributes used for all FindFirst's in EDirTree. Directory attribute is added or cleared when necessary(if the program searches for directories or just for files).
See also FileScan, SearchForFiles and BuildTree which use the value set by the SetFAttr procedure.
Example:
SetFAttr(archive+readonly); include Archive and readonly files in search.
Declaration
PROCEDURE ClearStat;
Description
This is the initcode of the unit. It resets all the Variables to zero or false (like DirsToo) and calls SetFAttr to let the unit include all files except volume-IDs.
The initcode is moved to a procedure so mainprograms can reset the unit, and because TopSpeed modula-2 doesn't allow overlayed units to have initcode.
Example:
ClearStat
Declaration
PROCEDURE FileScan(RootDir,FileName : PChar;Report:ReportProc);
Description
Filesearch in path RootDir and in its subdirectories, for files matching FileName (may be a wildcard, directories are regarded as files when DirsToo=TRUE). Files are reported to the procedure Report, with all information (path and Dos.SearchRec).
To quickly execute a procedure in every directory, enter "." as filename, and assign TRUE toDirsToo.
FileScan is quite powerfull, however if you want to do a very complex scan, or scan a certain drive or directory several (more than 2) times, look at the ScanTree, SearchForFiles and BuildTree combination.
Note: Notes about Tree building
Example:
PROCEDURE WriteOutput(Path:PathStr;FileData:SearchRec); FAR; {procedure variables are always FAR for BP, FPK doesn't care} BEGIN Write(Path,FileData.name,' ',FileData.size); END; BEGIN DirsToo:=FALSE; {EDirtree procedure, don't report directories, incase a directory with extension .pas exists} FileScan('c:\','*.pas',@WriteOutput); {searches for *.pas on entire 'c:\'} END.
Declaration
FUNCTION BuildTree(CONST RootDir: PChar):DirTreePoint;
Description
Searches path RootDir and adds all directories to a DirTreePoint type tree. A pointer to the created tree is returned.
See also
Example:
(Too complex. See DirTest.pp in this package)
Declaration
PROCEDURE SearchForFiles(Root:DirTreePoint;CONST Pattern:PChar;Select:DetectProc);
Description
Use after a BuildTree (creates the Root DirTreePointer), searches all directories in memory for occurance of Pattern, and adds those to the tree under the "files" field of all DirTreePoint's. Pattern is something like "*.txt" Select is a function which you supply to do additional checks. If this function returns TRUE the file will be added to the tree, if it returns FALSE it won't. If you don't want to use this feature, pass a procedure which always returns TRUE
Can be used several times, for more than one extension/pattern, however overlapping patterns will result in duplicate files. Somewhere in the future I will write a procedure which fixes this
Note: Notes about Tree building
See also
(Too complex. See DirTest.pp in this package)
Declaration
PROCEDURE ScanTree(Root : DirTreePoint;DoFile:FileProcFileProc;DoDir : DirProc);
Description
Use after a BuildTree and optinally one or more SearchForFiles.
This procedure scans the directory tree Root and runs DoFile for each found file in the tree. DoDir is also run for every directory when DirsToo=TRUE.
Note: Notes about Tree building
See also
(Too complex. See DirTest.pp in this package)
Declaration
PROCEDURE KillFileTree(VAR Root:DirTreePoint); Description
Use after a BuildTree and optionally one or more SearchForFiles.
This procedure simply removes a entire files-and-directory tree referenced by Root from memory.
Can also be used to eliminate unwanted parts of the tree. See also
(Too complex. See DirTest.pp in this package)
This is because the treebuilding routines scan at least twice. Once for directories, at least one for files. (to get only a directory structure you can also use filename='.' and DirsToo=TRUE with Filescan)
Also remember that a SearchForFiles is much slower than a ScanTree. So one SearchForFiles with *.* and some extra code in the procedure which ScanTree reports to is often faster than doing multiple SearchForFiles, or FileScans
Generally, one SearchForFiles per driveletter should be enough if you program smart, (I know, I don't do that in the demo, but that's to show that SearchForFiles CAN be run twice.)
Also, heavy caching(Win95, Dos with HyperDisk, and probably also Linux) smoothes the difference between the two search mechanisms