home *** CD-ROM | disk | FTP | other *** search
- {--------------------------------------------------------------}
- { Searcher }
- { }
- { General-purpose file search unit }
- { }
- { by Jeff Duntemann }
- { Turbo Pascal V5.0 }
- { Last update 7/25/88 }
- { }
- { From: COMPLETE TURBO PASCAL 5.0 by Jeff Duntemann }
- { Scott, Foresman & Co., Inc. 1988 ISBN 0-673-38355-5 }
- {--------------------------------------------------------------}
-
- {$F+}
- UNIT Searcher;
-
- INTERFACE
-
- USES DOS;
-
-
- { Note that this unit REQUIRES version 5.0 to compile! }
-
- TYPE
- HitProc = PROCEDURE(Foundit : SearchRec; InDirectory : String);
-
- PROCEDURE SearchAll(Directory: String;
- Spec : String;
- Attribute : Byte;
- DoIt : HitProc);
-
- PROCEDURE SearchOne(Directory : String;
- Spec : String;
- Attribute : Byte;
- Doit : Hitproc);
-
- PROCEDURE SearchCurrent(Spec : String; Attribute : Byte; Doit : Hitproc);
-
-
- IMPLEMENTATION
-
-
- {->>>>SearchAll<<<<--------------------------------------------}
- { }
- { UNIT FILE: SEARCHER.PAS -- Last Modified 6/29/88 }
- { }
- { This is a search "engine" that traverses the entire DOS }
- { directory tree of the current disk volume, looking for files }
- { that match a filespec passed in Spec, and an attribute byte }
- { passed in Attribute. Whenever a matching file is found, the }
- { found file's DTA is passed to a procedural parameter, which }
- { then takes some action using the information in the DTA. }
- { }
- { The underlying logic of using FIND FIRST and FIND NEXT is }
- { almost identical to that of the LOCATE.PAS program, with the }
- { the difference that LOCATE.PAS only displays information on }
- { the found files. Passing different procedures in HitProc }
- { allows SearchAll to perform any action on a found file that }
- { you care to code up as a procedural parameter. }
- {--------------------------------------------------------------}
-
- PROCEDURE SearchAll(Directory: String;
- Spec : String;
- Attribute : Byte;
- DoIt : HitProc);
-
- VAR
- CurrentDTA : SearchRec;
- TempDirectory,NextDirectory : String;
-
-
- BEGIN
- { First we look for any subdirectories. If any are found, }
- { we make a recursive call and search 'em too: }
-
- { Suppress unnecessary backslashes if we're searching the root: }
- IF Directory = '\' THEN
- TempDirectory := Directory + '*.*'
- ELSE
- TempDirectory := Directory + '\*.*';
-
- { Now make the FIND FIRST call for directories: }
-
- FindFirst(TempDirectory,$10,CurrentDTA);
-
-
- { Here's the tricky stuff. If we get an indication that there is }
- { at least one more subdirectory within the current directory, }
- { (indicated by lack of error codes 2 or 18) we must search it }
- { by making a recursive call to SearchDirectory. We continue }
- { recursing and returning from the searched subdirectories until }
- { we get a code indicating none are left. }
- WHILE (DOSError <> 2) AND (DOSError <> 18) DO
- BEGIN
- IF ((CurrentDTA.Attr AND $10) = $10) { If it's a directory }
- AND (CurrentDTA.Name[1] <> '.') THEN { and not '.' or '..' }
- BEGIN
- { Add a slash separating sections of the path if we're not }
- { currently searching the root: }
- IF Directory <> '\' THEN NextDirectory := Directory + '\'
- ELSE NextDirectory := Directory;
-
- { This begins with the current directory name, and copies }
- { the name of the found directory from the current DTA to }
- { the end of the current directory string. Then the new }
- { path is passed to the next recursive instantiation of }
- { SearchDirectory. }
- NextDirectory := NextDirectory + CurrentDTA.Name;
-
- { Here's where we call "ourselves." }
- SearchAll(NextDirectory,Spec,Attribute,DoIt);
-
- END;
- FindNext(CurrentDTA); { Now we look for more... }
- END;
-
- { Now we can search for files, once we've run out of directories. }
- { This is conceptually simpler, as recursion is not involved. }
- { We combine the path and the file spec into one string, and make }
- { the FIND FIRST call: }
-
- { Suppress unnecessary slashes for root search: }
- IF Directory <> '\' THEN
- TempDirectory := Directory + '\' + Spec
- ELSE TempDirectory := Directory + Spec;
-
- { Now, make the FIND FIRST call: }
- FindFirst(TempDirectory,Attribute,CurrentDTA);
-
- IF DOSError = 3 THEN { Bad path error }
- Writeln('Path not found; check spelling.')
-
- { If we found something in the current directory matching the filespec, }
- { call the procedural parameter to take some action on the found DTA: }
- ELSE IF (DOSError = 2) OR (DOSError = 18) THEN
- { Null; Directory is empty }
- ELSE
- BEGIN
- DoIt(CurrentDTA,Directory); { Call the procedural parameter }
- IF DOSError <> 18 THEN { More files are out there... }
- REPEAT
- FindNext(CurrentDTA); { Look for additional matches }
- IF DOSError <> 18 THEN { More entries exist }
- DoIt(CurrentDTA,Directory) { Call the procedural parameter }
- UNTIL (DOSError = 18) OR (DOSError = 2) { Ain't no more! }
- END
- END;
-
-
-
- {->>>>SearchOne<<<<--------------------------------------------}
- { }
- { UNIT FILE: SEARCHER.PAS -- Last Modified 5/28/88 }
- { }
- { This procedure is a subset of SearchAll, in that it only }
- { searches the directory specified in Directory, and not the }
- { entire directory tree of the current disk volume. In all }
- { other respects it operates the same way. }
- {--------------------------------------------------------------}
-
-
- PROCEDURE SearchOne(Directory : String;
- Spec : String;
- Attribute : Byte;
- Doit : Hitproc);
-
- VAR
- TempDirectory : String;
- CurrentDTA : SearchRec;
-
- BEGIN
- { Suppress unnecessary slashes for root search: }
- IF Directory <> '\' THEN
- TempDirectory := Directory + '\' + Spec
- ELSE TempDirectory := Directory + Spec;
-
- { Now, make the FIND FIRST call: }
- FindFirst(TempDirectory,Attribute,CurrentDTA);
-
- IF DOSError = 3 THEN { Bad path error }
- Writeln('Path not found; check spelling.')
-
- { If we found something in the current directory matching the filespec, }
- { call the procedural parameter to take some action on the found DTA: }
- ELSE IF (DOSError = 2) OR (DOSError = 18) THEN
- { Null; Directory is empty }
- ELSE
- IF DOSError <> 18 THEN { More files are out there... }
- BEGIN
- DoIt(CurrentDTA,Directory); { Call the procedural parameter }
- REPEAT
- FindNext(CurrentDTA); { Look for additional matches }
- IF DOSError <> 18 THEN { More entries exist }
- DoIt(CurrentDTA,Directory); { Call the procedural parameter }
- UNTIL (DOSError = 18) OR (DOSError = 2) { Ain't no more! }
- END
- END;
-
-
-
- {->>>>SearchCurrent<<<<----------------------------------------}
- { }
- { UNIT FILE: SEARCHER.PAS -- Last Modified 5/28/88 }
- { }
- { This procedure uses the same FIND FIRST/FIND NEXT logic of }
- { SearchAll and SearchOne, but only searches the current }
- { directory. It therefore does not need to be passed a }
- { parameter specifying the directory to be searched. }
- {--------------------------------------------------------------}
-
-
- PROCEDURE SearchCurrent(Spec : String; Attribute : Byte; Doit : Hitproc);
-
- VAR
- Directory : String;
-
- BEGIN
- GetDir(0,Directory); { Query DOS for the name of the current directory }
- SearchOne(Directory,Spec,Attribute,DoIt);
- END;
-
-
- END.