home *** CD-ROM | disk | FTP | other *** search
- PROGRAM ReadFile;
-
- {$B-,D+,R-,S-,T+,V-}
- {
- ┌────────────────────────────────────────────────────┐
- │ USES AND GLOBAL VARIABLES & CONSTANTS │
- └────────────────────────────────────────────────────┘
- }
-
- USES Crt, Dos;
-
- CONST
- NL = #13#10;
-
- TYPE
-
- FPtr = ^Dir_Rec;
-
- Dir_Rec = record { Double pointer record }
- DirName : string[12];
- DirNum : integer;
- Next : Fptr;
- END;
-
- Str_type = string[65];
-
- VAR
-
- Dir : str_type;
- Loop : boolean;
- Level : integer;
- Flag : array[1..5] of string[20];
- TreeOnly : boolean;
- FileTotal : longint;
- ByteTotal : longint;
- DirsTotal : longint;
- TooDeep : boolean;
- ColorCnt : byte;
-
- {
- ┌────────────────────────────────────────────────────┐
- │ PROCEDURE Beepit │
- └────────────────────────────────────────────────────┘
- }
-
- PROCEDURE Beepit;
-
- BEGIN
- SOUND (760); { Beep the speaker }
- DELAY (80);
- NOSOUND;
- END;
-
- {
- ┌────────────────────────────────────────────────────┐
- │ PROCEDURE Usage │
- └────────────────────────────────────────────────────┘
- }
-
- PROCEDURE Usage;
-
- BEGIN
- BEEPIT;
- WRITELN (
- 'Like the DOS TREE command, and similar to PC Magazine''s VTREE, but gives',NL,
- 'you a graphic representation of your disk hierarchical tree structure AND',NL,
- 'the number of files and total bytes in each tree node (optionally can be',NL,
- 'omitted). Also allows starting at a particular subdirectory rather than',NL,
- 'displaying the entire drive''s tree structure. Redirection of output and',NL,
- 'input is an option. ',NL,
- '',NL,
- 'USAGE: VTREE2 {path} {/t} {/r}',NL,
- '',NL,
- '/t or /T omits the number of files and total bytes information.',NL,
- '/r or /R activates redirection of input and output.',NL);
- Halt;
- END;
-
- {
- ┌────────────────────────────────────────────────────┐
- │ PROCEDURE Format_Num │
- └────────────────────────────────────────────────────┘
- }
-
- PROCEDURE Format_Num (Number : longint; VAR NumStr : string);
-
- BEGIN
- STR(Number,NumStr);
-
- IF (LENGTH (NumStr) > 6) THEN { Insert millions comma }
- INSERT (',',NumStr,(LENGTH(NumStr) - 5));
-
- IF (LENGTH (NumStr) > 3) THEN { Insert thousands comma }
- INSERT (',',NumStr,(LENGTH(NumStr) - 2));
-
- END;
-
- {
- ┌────────────────────────────────────────────────────┐
- │ PROCEDURE DisplayDir │
- └────────────────────────────────────────────────────┘
- }
-
- PROCEDURE DisplayDir (DirP : str_type; DirN : str_type; Levl : integer;
- NumSubsVar2 : integer; SubNumVar2 : integer;
- NumSubsVar3 : integer;
- NmbrFil : integer; FilLen : longint);
-
- {NumSubsVar2 is the # of subdirs. in previous level;
- NumSumsVar3 is the # of subdirs. in the current level.
- DirN is the current subdir.; DirP is the previous path}
-
- VAR
- BegLine : string;
- MidLine : string;
- Blank : string;
- WrtStr : string;
- NumFil : string;
- FilByte : string;
-
- BEGIN
-
- IF Levl > 5 THEN
- BEGIN
- BEEPIT;
- TooDeep := True;
- EXIT;
- END;
-
- Blank := ' '; { Init. variables }
- BegLine := '';
- MidLine := ' ──────────────────';
-
- IF Levl = 0 THEN { Special handling for }
- IF Dir = '' THEN { initial (0) dir. level }
- IF NOT TreeOnly THEN
- WrtStr := 'ROOT ──'
- ELSE
- WrtStr := 'ROOT'
- ELSE
- IF NOT TreeOnly THEN
- WrtStr := DirP + ' ──'
- ELSE
- WrtStr := DirP
- ELSE
- BEGIN { Level 1+ routines }
- IF SubNumVar2 = NumSubsVar2 THEN { If last node in subtree, }
- BEGIN { use └─ symbol & set flag }
- BegLine := '└─'; { padded with blanks }
- Flag[Levl] := ' ' + Blank;
- END
- ELSE { Otherwise, use ├─ symbol }
- BEGIN { & set flag padded with }
- BegLine := '├─'; { blanks }
- Flag[Levl] := '│' + Blank;
- END;
-
- CASE Levl OF { Insert │ & blanks as }
- 1: BegLine := BegLine; { needed, based on level }
- 2: Begline := Flag[1] + BegLine;
- 3: Begline := Flag[1] + Flag[2] + BegLine;
- 4: Begline := Flag[1] + Flag[2] + Flag[3] + BegLine;
- 5: Begline := Flag[1] + Flag[2] + Flag[3] + Flag[4] + BegLine;
- END; {end case}
-
- IF (NumSubsVar3 = 0) THEN { If cur. level has no }
- WrtStr := BegLine + DirN { subdirs., leave end blank}
- ELSE
- BEGIN
- WrtStr := BegLine + DirN + COPY(Midline,1,(13-LENGTH(DirN)));
- IF Levl < 5 THEN
- IF TreeOnly = False THEN
- WrtStr := WrtStr + '─┬─'
- ELSE
- WrtStr := WrtStr + '─┐ '
- ELSE { If level 5, special }
- BEGIN { end to indicate more }
- DELETE (WrtStr,LENGTH(WrtStr),1); { levels }
- WrtStr := WrtStr + '»';
- END;
- END;
- END; { End level 1+ routines }
-
- Format_Num (NmbrFil,NumFil);
- Format_Num (FilLen,FilByte);
-
- IF ODD(ColorCnt) THEN
- TextColor (3)
- ELSE
- TextColor (12);
- INC (ColorCnt);
-
- IF ((Levl < 4) OR ((Levl = 4) AND (NumSubsVar3=0))) AND NOT TreeOnly THEN
- WRITELN (WrtStr,'':(65 - LENGTH(WrtStr)),NumFil:3,FilByte:11)
- ELSE
- WRITELN (WrtStr); { Write # of files & bytes }
- { only if it fits, else }
- END; { write only tree outline }
-
-
- {
- ┌────────────────────────────────────────────────────┐
- │ PROCEDURE DisplayHeader │
- └────────────────────────────────────────────────────┘
- }
-
- PROCEDURE DisplayHeader;
-
- BEGIN
- WRITELN ('DIRECTORIES','':52,'FILES',' BYTES');
- WRITELN ('═══════════════════════════════════════════════════════════════════════════════');
- END;
-
- {
- ┌────────────────────────────────────────────────────┐
- │ PROCEDURE DisplayTally │
- └────────────────────────────────────────────────────┘
- }
-
- PROCEDURE DisplayTally;
-
- VAR
- AllFiles : string;
- AllBytes : string;
-
- BEGIN
- Format_Num (ByteTotal, AllBytes);
- Format_Num (FileTotal, AllFiles);
- WRITELN('':63,'════════════════');
- WRITELN('NUMBER OF DIRECTORIES: ', DirsTotal:3, '':29,
- 'TOTALS: ', AllFiles:5, AllBytes:11);
- END;
-
- {
- ┌────────────────────────────────────────────────────┐
- │ PROCEDURE ReadFiles │
- └────────────────────────────────────────────────────┘
- }
-
- PROCEDURE ReadFiles (DirPrev : str_type; DirNext : str_type;
- SubNumVar1 : integer; NumSubsVar1 : integer);
-
- VAR
- FileInfo : SearchRec;
- FileBytes : longint;
- NumFiles : integer;
- NumSubs : integer;
- Dir_Ptr : FPtr;
- CurPtr : FPtr;
- FirstPtr : FPtr;
-
- BEGIN
- FileBytes := 0;
- Numfiles := 0;
- NumSubs := 0;
- Dir_Ptr := nil;
- CurPtr := nil;
- FirstPtr := nil;
-
- IF Loop THEN FindFirst (DirPrev + DirNext + '\*.*', AnyFile, FileInfo);
- Loop := False; { Get 1st file }
-
- WHILE DosError = 0 DO { Loop until no more files }
- BEGIN
- IF (FileInfo.Name <> '.') AND (FileInfo.Name <> '..') THEN
- BEGIN
- IF (FileInfo.attr = directory) THEN { If fetched file is dir., }
- BEGIN { store a record with dir. }
- NEW (Dir_Ptr); { name & occurence number, }
- Dir_Ptr^.DirName := FileInfo.name;{ and set links to }
- INC (NumSubs); { other records if any }
- Dir_Ptr^.DirNum := NumSubs;
- IF CurPtr = nil THEN
- BEGIN
- Dir_Ptr^.Next := nil;
- CurPtr := Dir_Ptr;
- FirstPtr := Dir_Ptr;
- END
- ELSE
- BEGIN
- Dir_Ptr^.Next := nil;
- CurPtr^.Next := Dir_Ptr;
- CurPtr := Dir_Ptr;
- END;
- END
- ELSE
- BEGIN { Tally # of bytes in file }
- FileBytes := FileBytes + FileInfo.size;
- INC (NumFiles); { Increment # of files, }
- END; { excluding # of subdirs. }
- END;
- FindNext (FileInfo); { Get next file }
- END; {end WHILE}
-
- ByteTotal := ByteTotal + FileBytes;
- FileTotal := FileTotal + Numfiles;
- DirsTotal := DirsTotal + NumSubs;
-
- DisplayDir (DirPrev, DirNext, Level, NumSubsVar1, SubNumVar1, NumSubs,
- NumFiles, FileBytes); { Pass info to & call }
- INC (Level); { display routine, & inc. }
- { level number }
-
-
- WHILE (FirstPtr <> nil) DO { If any subdirs., then }
- BEGIN { recursively loop thru }
- Loop := True; { ReadFiles proc. til done }
- ReadFiles ((DirPrev + DirNext + '\'),FirstPtr^.DirName,
- FirstPtr^.DirNum, NumSubs);
- FirstPtr := FirstPtr^.Next;
- END;
-
-
- DEC (Level); { Decrement level when }
- { finish a recursive loop }
- { call to lower level of }
- { subdir. }
- END;
-
- {
- ┌────────────────────────────────────────────────────┐
- │ PROCEDURE Read_Parm │
- └────────────────────────────────────────────────────┘
- }
-
- PROCEDURE Read_Parm;
-
- VAR
- Cur_Dir : string;
- Param : string;
- i : integer;
-
- BEGIN
-
- IF ParamCount > 3 THEN Usage;
- Param := '';
-
- FOR i := 1 TO ParamCount DO { If either param. is a T, }
- BEGIN { set TreeOnly flag }
- Param := ParamStr(i);
- IF Param[1] = '/' THEN
- CASE Param[2] OF
- 't','T': BEGIN
- TreeOnly := True;
- IF ParamCount = 1 THEN EXIT;
- END; { Exit if only one param }
-
- 'r','R': BEGIN
- ASSIGN (Input,''); { Override CRT unit, & }
- RESET (Input); { make input & output }
- ASSIGN (Output,''); { redirectable }
- REWRITE (Output);
- IF ParamCount = 1 THEN EXIT;
- END; { Exit if only one param }
- '?' : Usage;
- ELSE
- Usage;
- END; {case}
- END;
-
- GETDIR (0,Cur_Dir); { Save current dir }
- FOR i := 1 TO ParamCount DO
- BEGIN
- Param := ParamStr(i); { Set var to param. string }
- IF (POS ('/',Param) = 0) THEN
- BEGIN
- Dir := Param;
- {$I-} CHDIR (Dir); { Try to change to input }
- IF IOResult = 0 THEN { dir.; if it exists, go }
- BEGIN { back to orig. dir. }
- {$I+} CHDIR (Cur_Dir);
- IF (POS ('\',Dir) = LENGTH (Dir)) THEN
- DELETE (Dir,LENGTH(Dir),1); { Change root symbol back }
- EXIT { to null, 'cause \ added }
- END { in later }
- ELSE
- BEGIN
- BEEPIT;
- WRITELN ('No such directory -- please try again.');
- HALT;
- END;
- END;
- END;
-
- END;
-
- {
- ┌────────────────────────────────────────────────────┐
- │ MAIN PROGRAM │
- └────────────────────────────────────────────────────┘
- }
-
- VAR
-
- Version : string;
-
- BEGIN
-
- Version := 'Version 1.3, 6-27-88 -- Public Domain by John Land';
- { Sticks in EXE file }
-
- Dir := ''; { Init. global vars. }
- Loop := True;
- Level := 0;
- TreeOnly := False;
- TooDeep := False;
- FileTotal := 0;
- ByteTotal := 0;
- DirsTotal := 1; { Always have a root dir. }
- ColorCnt := 1;
-
- ClrScr;
-
- IF ParamCount > 0 THEN Read_Parm; { Deal with any params. }
-
- IF NOT TreeOnly THEN DisplayHeader;
-
- ReadFiles (Dir,'',0,0); { Do main read routine }
-
- IF NOT TreeOnly THEN DisplayTally; { Display totals }
-
- IF TooDeep THEN
- WRITELN (NL,NL,'':22,'» CANNOT DISPLAY MORE THAN 5 LEVELS «',NL);
- { If ReadFiles detects >5 }
- { levels, TooDeep flag set}
-
- END.