home *** CD-ROM | disk | FTP | other *** search
- /* tree.rexx */
-
- /*
- Format
-
- TREE [[DIR] <dir> | FROM <file>] [P[AT] <pat>] [DIRS] [FILES]
- [SORT] [{AFTER | SINCE} <date>] [{BEFORE | UPTO} <date>]
- [FLAGS <flags>] [MIN <number>] [MAX <number>]
- [[NO]COMMENTS] [MACRO <name>] [TO <file>] [DIRLIST <file>]
-
- Descend through directory tree and list full filename to STDOUT
- based on selection criteria supplied on the command line. A file
- must meet all the selection criteria to be written to the output.
-
- DIR <dir>
- Directory to begin at. If not specified, the current directory
- is assumed, unless a FROM file is specified.
-
- FROM <file>
- Instead of specifying a beginning directory, a file may be
- specified that contains the list of directories to scan.
- This can speed up multiple calls to the same directory tree
- by specifying an output file with the DIRLIST qualifier, then
- on successive calls to TREE using that file as the FROM file.
- This eliminates the directory scan phase on later calls.
-
- PAT <pat>
- ARP/AmigaDOS pattern to match. All directories in the tree are
- checked, reguardless of whether they match the supplied pattern.
-
- DIRS,FILES
- Select based on file type. If neither specified, both files and
- directories are listed.
-
- SORT
- Sort output by directory and filename. All files are listed
- before the files in sub-directories. This qualifier does not
- control sorting of the directory file. It is always sorted.
-
- BEFORE | UPTO, AFTER | SINCE <date>
- Select based on date of file. <date> is in format expected by
- the DOS LIST command, although the "/" character may be used
- in place of the dash ("-").
-
- FLAGS <flags>
- Select based on protection code. <flags> is list of flags that
- must be set or cleared. If the flag is lowercase, that flag
- must be set. If the flag is uppercase, that flag must be
- cleared. If absent, the flag is not checked.
-
- MIN,MAX <number>
- Select based on file size. Minimum and/or maximum size of file
- in bytes. Not good to use if only selecting directories.
-
- [NO]COMMENTS
- Select based on the presence or absence of a comment. You
- cannot specify both COMMENTS and NOCOMMENTS.
-
- MACRO <name>
- Name of an Arexx macro. This macro will be called only if all the
- other tests pass. The macro is assumed to be in the REXX: directory,
- with a file extension of ".tree". The parameters passed are
- (<filename>, <type>, <bytes>, <blocks>, <protection-flags>, <days>,
- <minutes>, <ticks>, <comment>). The macro MUST return a string value
- which, if not null, is written to the output instead of the filename.
- Of course, the macro may DO something to the file, in which case the
- return value can act as a "quiet" or "verbose" switch.
-
- TO <file>
- Send output to indicated file instead of STDOUT. This does NOT
- include direct output from the MACRO, if specified.
-
- DIRLIST <file>
- Normally, a temporary file is created that holds the list of
- directories in the tree, and deleted at the end. This file can
- be saved using this qualifier and supplying the name of the file
- to contain the list. The directory list is only sorted if the
- SORT qualifier is also present. See the FROM qualifier description.
-
- */
-
- /*
- TREE DIR,FROM/K,P=PAT/K,DIRS/S,FILES/S,SORT/S,AFTER=SINCE/K,BEFORE=UPTO/K,
- FLAGS/K,MIN/K,MAX/K,COMMENTS/S,NOCOMMENTS/S,MACRO/K,TO/K,DIRLIST/K
- */
-
- /* External routines: DirIndex.rexx */
-
- signal on failure; signal on break_c
- options failat 10
- call addlib 'rexxextra.library',-20,-30,0
-
- facility = 'Tree'
- retcode = 0
-
- template = ,
- 'DIRS/S,FILES/S,SORT/S,COMMENTS/S,NOCOMMENTS/S,FROM/K,TO/K,P=PAT/K,' || ,
- 'AFTER=SINCE/K,BEFORE=UPTO/K,FLAGS/K,MIN/K,MAX/K,MACRO/K,' || ,
- 'DIRLIST/K,DIR'
- dtemplate = 'DIR,FROM/K,DIRLIST/K,TO/K,P=PAT/K,DIRS/S,FILES/S,SORT/S,' || ,
- 'AFTER=SINCE/K,BEFORE=UPTO/K,FLAGS/K,MIN/K,MAX/K,' || ,
- 'COMMENTS/S,NOCOMMENTS/S,MACRO/K'
- args. = ''
- tmpfile = 't:TREE.'||pragma('ID'); args.DIRLIST = tmpfile'.1'
-
- parse value 'TREETMPFILE STDOUT 1 0 10000000 0 1' with ,
- inhandle outhandle j args.MIN args.MAX nfl simple ,
- . listcmd args.DIR args.TO args.FROM args.MACRO simplecmd
-
- parse arg g_c
- do while g_c='?'
- options prompt dtemplate': ' /* this template is */
- parse pull g_c /* displayed to the user */
- if g_c='?' then do
- g_s=sourceline(3)
- if pos('/*',g_s)=0 then break; if pos('*/',g_s)>0 then break
- say
- g_s=sourceline(4)
- do i=5 while pos('*/',g_s)=0; say g_s; g_s=sourceline(i); end
- say
- end
- end
- interpret Cparse(g_c,template,'args')
- if args.ERRCODE > 1 then do; say facility'-E-BADARGS,' args.ERRTEXT; exit 5; end
-
- if args.AFTER ~= '' then
- listcmd = listcmd 'SINCE ' || translate(args.AFTER,'-','/')
- if args.BEFORE ~= '' then
- listcmd = listcmd 'UPTO ' || translate(args.BEFORE,'-','/')
- if args.P ~= '' then
- listcmd = listcmd 'PAT "' || args.P || '"'
- if args.DIRS then listcmd = listcmd 'DIRS'
- if args.SORT then listcmd = listcmd 'SORT'
- if args.FILES then listcmd = listcmd 'FILES'
- if args.MACRO ~= '' then do
- args.MACRO = fparse(pragma('D'),args.MACRO,'REXX:.tree')
- simple = 0
- end
- if args.FLAGS ~= '' then do
- parse var args.FLAGS fl.1 +1 fl.2 +1 fl.3 +1 fl.4 +1 fl.5 +1 fl.6 +1 fl.7 +1 fl.8 +1 .
- nfl = length(args.FLAGS)
- simple = 0
- end
- if (args.MIN > 0) | (args.MAX < 10000000) then simple = 0
-
- /* simple check of input for validity */
- if (args.COMMENTS & args.NOCOMMENTS) then
- call sayerror("Can't specify both 'COMMENTS' and 'NOCOMMENTS'")
-
- if ~datatype(args.MIN,'N') | ~datatype(args.MAX,'N') then
- call sayerror("MIN and/or MAX value must be numeric")
-
- if (args.MIN > args.MAX) then call sayerror("MIN can't be more than MAX")
-
- if (args.FROM ~= '' & args.DIR ~= '') then
- call sayerror("Can't have both a FROM file and a DIR")
-
- if args.FROM ~= '' then args.DIRLIST = args.FROM
- else do
- if args.DIR = '' then args.DIR = pragma('D') /* default is current */
- if ~exists(args.DIR) then call sayerror(args.DIR' does not exist')
- 'DirIndex' args.DIR args.DIRLIST /* make list of dirs */
- end
- if args.TO ~= '' then
- if simple then do
- simplecmd = '>>'args.TO
- if exists(args.TO) then call delete args.TO
- else nop
- end
- else if open('OUTFILE',args.TO,'w') then outhandle = 'OUTFILE'
- else exit 20
- if ~simple then simplecmd = 'TO' tmpfile
- 'ExecIO read' args.DIRLIST 'stem dirs.'
- /*
- Main Loop
- */
- do jj = 1 to dirs.0
- pdir = dirs.jj
- if word(statef(pdir),1) = 'DIR' then do
- 'LIST' simplecmd listcmd 'LFORMAT="%S%S" "'pdir'"'
- if ~simple then do
- if ~open(inhandle,tmpfile,'r') then exit 20
- pfile = readln(inhandle)
- do j = 1 while ~eof(inhandle)
- parse value statef(pfile) with type bytes blocks proflags days minutes ticks comment
- if datatype(ticks,'N') then do
- comment = substr(comment,2)
- pflags = upper(compress(proflags,'-'))
- ok = 1 /* assume the file will pass our tests */
- if (bytes < args.MIN) | (bytes > args.MAX) | (args.COMMENTS & comment = '') | ,
- (args.NOCOMMENTS & comment ~= '') then ok = 0
- else do i = 1 to nfl
- if (pos(fl.i,'hsparwed') > 0) & (pos(upper(fl.i),pflags) = 0) then ok = 0
- else if (pos(fl.i,'HSPARWED') > 0) & (pos(fl.i,pflags) > 0) then ok = 0
- end i
- if ok & (args.MACRO ~= '') then do
- interpret 'mr = "'args.MACRO'"(pfile,' || ,
- 'type,bytes,blocks,proflags,days,minutes,ticks,comment)'
- if mr = '' then ok = 0; else pfile = mr
- end
- if ok then call writeln outhandle, pfile
- end
- pfile = readln(inhandle)
- end j
- call close inhandle
- end
- end
- end jj
-
- GetOut:
- if outhandle ~= 'STDOUT' then call close outhandle
- 'Delete' tmpfile'(%|.?) quiet'
- exit retcode
-
- break_c:
- break_d:
- break_e:
- break_f:
- say facility'-E-BREAK, Control-C interrupt'
- exit 20
- failure:
- say facility'-E-FAIL, Line:' sigl', Error:' rc; retcode = rc; signal GetOut
- syntax:
- say facility'-E-SYNTAX, Line:' sigl', Error:' rc; retcode = rc; signal GetOut
- error:
- say facility'-E-ERROR, Line:' sigl', Error:' rc; retcode = rc; signal GetOut
-
- sayerror: procedure expose facility
- parse arg x
- say facility'-E-ERROR,' x
- retcode = 10
- signal GetOut
-
-