/* 25 Jan 2003. Daniel Hellerstein (danielh@crosslink.net)
DirTree ver 1.16d
Sort (and display) all files in a directory tree by filename.
Also supports directory summary capabilities.
You may freely use this utility,
You may also find the 3 procedures used here to be useful.
These are:
resolve_filename: return a fully qualified filename, given
a relative filename and directory information
StemSort: sort a stem variable (using a bubble sort)
dir_exists: detects whether a directory exists
Standard disclaimer:
This program, and its included procedures, may be
freely used, but you use them at your own risk.
For usage instructions, enter DIRTREE ? at an os/2 command prompt.
*/
/***** -- User changeable parameters ****/
/* assume that "periodless" names refer to directories
1 = Yes
0 = No
If 1, then f:\dir1 means "search for *.* in f:\dir1"
If 0, then F:\dir1 means "search for dir1 in F:\ "
In any case, F:\DIR1\ means "search for *.* in f:\dir1, and
F:\DIR1. means "search for DIR.1 in F:\" */
assume_dir=1
/* color used in "duplicate file finder mode" html output (this
color highlights the filename, subsequent rows contain path of duplicate files) */
bgcolor='#55aaaa'
/* used as a filler when the file name has not changed */
filler=' "" '
/* suppresses bold highlighting (set NOANSI=1 if you are getting odd
characters displayed */
noansi=0
/* default output file (if -FILE is given with no argument ) */
outfile='DIRTREE.LST'
/* By default, should a listing display date and size info.
ShowInfo=1 : yes
ShowInfo=0 : no */
showinfo=1
/* character used to indicate depth of subdirectory
(used with -DIRSUMMARY option */
subflag='$'
/* program string for displaying html output */
vu_prog='NETSCAPE -l en '
/**** End of user changeable parameters ****/
parse arg aa
parse var aa dirfile '-' astuff
if astuff<>'' then astuff='-'||astuff
/****/
/* set character display attributes */
if noansi=1 then do
normal='';bold='';aesc=''
end
else do
aesc='1B'x
normal=aesc||'[0;m'
bold=aesc||'[1;m'
end /* do */
if aa='?' | strip(aa)='-?' | strip(aa)='/?' then do
say bold'DirTree ver 1.16d:'normal' List files and/or subdirectories in a directory tree. '
say
say bold"Usage:"normal" x:>DIRTREE directory\file_pattern [-options] "
say " Where: "bold"directory"normal" = directory tree to list (default is current directory) "
say " "bold"file_pattern"normal" = a file pattern (* is the default)"
say " or, you can use dir1\file1 dir2\file2 ... to list multiple 'trees' "
say " "bold"Options include:"normal
say ' -SUMMARY = Just display a summary (#files/#bytes). '
say " -Onxds = Sort by n(ame), x(tension),d(ate), and/or s(ize). "
say " The default is to sort by name only."
say " -D = Decending sort (default is ascending). "
say " "
say " To list all options, enter DIRTREE ?? "
say
say bold"Examples:"normal" x:>dirtree \archive1\*.zip -Ond -D "
say " x:>dirtree -summary "
say " x:>dirtree f:\archive1\*.zip e:\projects\* -SHORT -FILEONLY A.LST "
say ' x:>dirtree "pets\My Cat*.*" -SHORT -FILEONLY A.LST '
say " x:>dirtree * -x \OLD \ARCHIVE "
say bold"Or,"normal" enter DIRTREE at a command prompt (with no arguments) to be prompted. "
exit
end
if dirfile='??' then do
say ' '||bold||"Options (DirTree ver 1.16d):"||normal
say ' -CT = Count of files with this "filename"'
say " -D = Decending sort (default is ascending) "
say ' -DIRSUMMARY = Display summary of each directory '
say ' (in dir: #files/#bytes; in subtree: subdirs/files/bytes) '
say ' -DUP = Find duplicate files (-Ondxs will be suppressed)'
say ' -DUP NOCRC = Find duplicate files, but do NOT check file CRC '
say ' -FILE filename.ext = Write results to filename.ext '
say ' -FILEONLY file.ext = same as -FILE, and do not display results on screen'
say ' -HTML file.ext = Write results using HTML formatting '
say ' -HTML_VU file.ext = Same as -HTML, and run Netscape to view file.ext '
say " -Onxds = Sort by n(ame), x(tension), d(ate), and/or s(ize) "
say " -PAUSE nn = Pause every nn lines. If nn not listed, pause every 20 lines"
say ' -SHORT,-LONG,-VERYLONG = Style of display '
say ' -SUMMARY = Display summary (#files/#bytes); '
say ' (do NOT display matching files)'
say ' -X xstr = Exclude files that contain xstr in their fully qualifed name'
say ' Xstr can contain several space delimited substrings'
say ' *:filename = Search ALL drives for filename '
say ' LOCAL:filename = Search ALL LOCAL drives for filename '
say ' REMOTE:filename = Search ALL REMOTE (LAN) drives for filename '
exit
end /* do */
say
/*--- Load REXX libraries ----- */
/* Load up advanced REXX functions */
foo=rxfuncquery('sysloadfuncs')
if foo=1 then do
call RxFuncAdd 'SysLoadFuncs', 'RexxUtil', 'SysLoadFuncs'
call SysLoadFuncs
end
foo=rxfuncquery('rexxlibregister')
if foo=1 then do
call rxfuncadd 'rexxlibregister','rexxlib', 'rexxlibregister'
call rexxlibregister
end
gotrexxlib=rxfuncquery('rexxlibregister')
sortorder=''
dopause=0
pause_after=20 /* pause every 20 lines */
isdescend=0
docount=0
dolong=0
lmxdate=14
dosummary=0
dodirsummary=0
toscreen=1
tofile=0
nbdd=0
excstring=''
dohtml=0
htmlview=0
duplook=0
if dirfile='' & (abbrev(translate(astuff),'-SUM')+abbrev(translate(astuff),'-DIRS'))>0 then
dirfile='*.*'
if dirfile<>'' then do
if dirfile='*' then dirfile='*.*'
/*if assume_dir=1 & pos('.',dirfile)=0 & right(strip(dirfile),1)<>"\" then dirfile=strip(dirfile)||'\' */
if pos('"',dirfile)=0 then do
dirfile=space(dirfile)
dirfile=translate(dirfile,'+',' ')
bdd=dirfile
end
else do /* parse out " xxx " stuff */
t1=dirfile
bdd=''
do forever
if t1='' then leave
parse var t1 a1 '"' a2 '"' t1
if a1<>'' then do
bdd=bdd'+'strip(a1)
end
if a2<>'' then do
bdd=bdd'+'strip(a2)
end
end
end
bdd=strip(bdd,'l','+')
/* pull out each subdir, and fix */
do until bdd=''
parse var bdd dirfile '+' bdd
dirf=translate(dirfile)
/* check for *: syntax, IF found, expand */
if abbrev(strip(dirf),'*:')=1 | ,
abbrev(strip(dirf),'LOCAL:')=1 | ,
abbrev(strip(dirf),'REMOTE:')=1 then do
parse var dirfile XX ':' dirfile1
XX=translate(STRIP(XX))
IF XX='*' then XX='USED'
oy=sysdrivemap(,XX)
do until oy=''
parse var oy aa oy
bdd=strip(aa)||dirfile1||'+'||bdd
end /* do */
iterate
end
nbdd=nbdd+1
adrive=''
if pos(':',dirfile)>0 then do
parse var dirfile adrive ':' dirfile
adrive=adrive':'
end
dirfile=translate(dirfile,'\','/')
apath=''
aname=dirfile
if assume_dir=1 & pos('.',dirfile)=0 & right(strip(dirfile),1)<>"\" ,
& pos('*',dirfile)=0 then
dirfile=strip(dirfile)||'\'
ii=lastpos('\',dirfile)
if ii>0 then do
apath=left(dirfile,ii)
aname=substr(dirfile,ii+1)
end
if aname='' then aname='*.*'
filename.nbdd=aname
adir.nbdd=strip(adrive||apath)
end
astuff=translate(astuff)||' '
if pos('-DIR',astuff)>0 then dodirsummary=1
if pos('-D ',astuff)>0 then isdescend=1
if pos('-CT',astuff)>0 then docount=1
if pos('-LONG',astuff)>0 then dolong=1
if pos('-VERYLONG',astuff)>0 then dolong=2
if pos('-INFO',astuff)>0 then do
dolong=0 ; showinfo=1 /* normal, with date & size */
end
if pos('SHORT',astuff)>0 then dolong=-1
if pos('-SUM',astuff)>0 then dosummary=1
if pos('-X',astuff)>0 then do
parse upper var astuff . '-X ' excstring '-' astuff ; excstring=strip(excstring)
end
if pos('-DUP',astuff)>0 then do
parse upper var astuff . '-DUP ' a23 '-' . ; parse var a23 a2 .
duplook=2
if abbrev(a2,'NOCRC')=1 then duplook=1
end
if pos('-HTML',astuff)>0 then do
dohtml=1
tofile=1
toscreen=0
parse upper var astuff . '-HTML' a23 '-' . ; parse var a23 a2 a3 .
if right(strip(a2),2)='VU' |abbrev(strip(a2),'VIEW')=1 then do
htmlview=1
a2=a3
end
a2=strip(a2)
if a2='' then a2=outfile
if stream(a2,'c','query exists')=' ' then do
say "Writing HTML results to "a2
end
else do
say "OverWriting HTML results to: "a2
foo=sysfiledelete(a2)
end
foo=stream(a2,'c','open write')
if foo<>'READY:' then do
say "Sorry, can not write to: "a2
exit
end
outfile=a2
call ini_html /* initialize html stuff in outfile */
end
if pos('-PAUSE',astuff)>0 then do
dopause=1
parse upper var astuff . '-PAUSE' a23 '-' . ; parse var a23 a2 .
if datatype(a2)='NUM' then
pause_after=max(1,a2)
else
pause_after=20
end
if pos('-FILE',astuff)>0 then do
tofile=1
parse upper var astuff . '-FILE' a23 '-' . ; parse var a23 a2 a3 .
if strip(a2)='ONLY' then do
toscreen=0
a2=a3
end
a2=strip(a2)
if a2='' then a2=outfile
if stream(a2,'c','query exists')=' ' then do
say "Writing results to "a2
end
else do
say "OverWriting results to: "a2
foo=sysfiledelete(a2)
end
foo=stream(a2,'c','open write')
if foo<>'READY:' then do
say "Sorry, can not write to: "a2
exit
end
outfile=a2
end
if dolong=-1 then do
filler=' '
lmxdate=8
end
parse var astuff . '-O' sortorder .
tt1='' ; tt2=''
if htmlview=1 then do
tt1='' ; tt2=''
end
do yy=1 to nbdd
adir.yy=resolve_filename('',adir.yy,,1)
if adir.yy='' then do
say "No such directory: "adir.yy
exit
end
end
if nbdd=1 then do
call dosay "Searching in: "||tt1||adir.1||tt2
call dosay " for: "||tt1||filename.1||tt2
end
else do
do yy=1 to nbdd
call dosay "Searching in: "||tt1||adir.yy||tt2
call dosay " for: "||tt1||filename.yy||tt2
end
end
if excstring<>'' then do
do www=1 to words(excstring)
if www=1 then
call dosay "Excluding files that match: *"||tt1||strip(word(excstring,www))||"*"||tt2
else
call dosay " : *"||tt1||strip(word(excstring,www))||"*"||tt2
end
end
end
else do /* from keyboard */
say bold'DirTree ver 1.16d:'normal' sort files (and subdirectories) in & under a directory.'
call charout," Starting directory: "
parse pull adir
adir=resolve_filename('',adir,,1)
if adir='' then do
say "No such directory: "adir
exit
end
call charout, " Files to find (default=*): "
parse pull filename
if filename='' then filename='*'
adir.1=adir
filename.1=filename
nbdd=1
dosummary=yesno(' Summary stats only (Y=yes)?',,'N')
if dosummary<>1 then do
sortorder=1+yesno(' Sort order: ','Date Size Name Xtension ','N')
sortorder=substr('DSNE',sortorder,1)
isdescend=yesno(' Display order ','Ascending Descending','A')
dolong=yesno('Info to display ','Short Info VeryLong ','I')
if dolong=1 then do
dolong=0; showinfo=1
end
dopause=yesno('Pause every 20 lines ',,'Y')
end
else do
dosummary=1
isdecend=0
end
end
/* ready to rumble */
do jj=1 to nbdd
ddd=adir.jj
if length(ddd)=3 then ddd=strip(ddd,,'\')
else
if dir_exists(ddd)=0 then do
say "% No such directory: "adir.jj
exit
end
end
if dosummary=1 | dodirsummary=1 then do /* just # files, # bytes, and # dirs? */
dohtml=0 /* html only for file listing */
foo=dir_summary(nbdd)
signal alldone
end
if dohtml=1 then dopause=0
if sortorder='' then sortorder='N'
fils.=0
iat=0
do mm=1 to nbdd
oo=sysfiletree_FILES(adir.mm||filename.mm,'tfils.','FTS')
do iuu=1 to tfils.0
iat=iat+1
fils.iat=tfils.iuu
end /* do */
fils.0=iat
end
/* grab the files */
lmxname=0; lmxsize=0 ;mm=0
lmxpath=0
crcs.=''
if duplook=2 then say " ... computing CRCs for matching files "
do mm0=1 to fils.0
mm=mm+1
parse var fils.mm0 date.mm size.mm . aa .
if excstring<>'' then do
do www=1 to words(excstring)
excstring1=strip(word(excstring,www))
if pos(excstring1,translate(aa))>0 then do
mm=mm-1
iterate mm0
end
end
end
nam.mm=translate(filespec("n",aa)); path.mm=filespec('p',aa)
if duplook>1 then crcs.mm=filecrc(aa)
if nbdd>1 | dohtml=1 then path.mm=translate(filespec("D",aa))||path.mm
lmxsize=max(length(size.mm),lmxsize)
lmxname=max(length(nam.mm),lmxname)
lmxpath=max(length(path.mm),lmxpath)
if left(date.mm,2)<80 then
date.mm='20'||date.mm
else
date.mm='19'||date.mm
end
call dosay "# of matching files= " mm
if duplook>0 then do
sortorder='NSCD'
end
srtx.=''
kk=0
do ll2=1 to mm
do ll=1 to length(sortorder)
atype=substr(sortorder,ll,1)
select
when atype='N' then do
srtx.ll2=srtx.ll2||left(nam.ll2,lmxname+1,' ')
end
when atype='X' then do
parse upper var nam.ll2 . '.' anextx .
srtx.ll2=srtx.ll2||left(anextx,lmxname+1,' ')
end
when atype='S' then do
srtx.ll2=srtx.ll2||right(size.ll2,lmxsize+1,'0')
end
when atype='D' then do
srtx.ll2=srtx.ll2||left(date.ll2,15,' ')
end
when atype='C' then do
srtx.ll2=srtx.ll2||left(crcs.ll2,18,' ')
end
otherwise do
nop
end
end /* select */
end /* do */
srtx.ll2=srtx.ll2||right(ll2,7,' ')
end /* do */
srtx.0=mm
if srtx.0>0 then do /* any matches? */
if duplook=1 then call dosay 'Duplicate file find (without using CRC)'
if duplook=2 then call dosay 'Duplicate file find'
if duplook=0 then call dosay "Sorting by " sortorder " ... "
if dohtml=1 then do
call lineout outfile,''
if duplook=0 then do /* don't bother with jump line if dup file find mode */
do igoo=1 to 26
alet=d2c(igoo+64)
call lineout outfile,''Alet' '
end
end
call lineout outfile,'
'||a2||' | ' end else do oldddt=ddt if dohtml=0 then call dosay ' '||left(path.ith,lmxpath+4,' ')||' ['||ddt||']' else call dosay '|
'||a2||' | '||ddt||' | ' end end else do /* not a duplicate, start new list */ ssz=strip(size.ith) nuniques=nuniques+1 select when ssz>10000000 then do ssz=left(ssz,length(ssz)-5)/10 ssz=ssz||'m' say " gooooob " ssz end when ssz>9999 then do ssz=left(ssz,length(ssz)-2)/10 ssz=ssz||'k' end otherwise nop end ddt=substr(date.ith,3) ddt=overlay(':',ddt,length(ddt)-2,1) ddt=overlay(' ',ddt,length(ddt)-5,1) oldddt=ddt if dohtml=0 then call dosay left(nam.ith,lmxname,' ')||' ('||ssz||' '||crcs.ith||')' else call dosay '
'||nam.ith||' | '||ssz||' '||crcs.ith||' | ' pth=path.ith a2=''||strip(pth)||'' if dohtml=0 then call dosay ' '||left(path.ith,lmxpath+4,' ')||' ['||ddt||']' else call dosay '
'||a2||' | '||ddt||' | ' olddup=newd end iterate end /* if here, not -DUP */ a2=left(nam.ith,lmxname) if a2=oldname then do /*always list filename */ mold=1 a2=left(filler,lmxname,' ') ict=ict+1 end else do /* new name */ mold=0 oldname=a2 if docount=1 then call dosay '('ict') 'tmpline ict=1 end if dohtml=1 & mold=0 then do a2='