home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 509.lha / RexxExtraLibrary_v1.2 / rexx / Tree.rexx < prev    next >
OS/2 REXX Batch file  |  1991-05-06  |  8KB  |  234 lines

  1. /* tree.rexx */
  2.  
  3. /*
  4.      Format
  5.  
  6.        TREE [[DIR] <dir> | FROM <file>] [P[AT] <pat>] [DIRS] [FILES]
  7.         [SORT] [{AFTER | SINCE} <date>] [{BEFORE | UPTO} <date>]
  8.         [FLAGS <flags>] [MIN <number>] [MAX <number>]
  9.         [[NO]COMMENTS] [MACRO <name>] [TO <file>] [DIRLIST <file>]
  10.  
  11.    Descend through directory tree and list full filename to STDOUT
  12.    based on selection criteria supplied on the command line. A file
  13.    must meet all the selection criteria to be written to the output.
  14.  
  15.      DIR <dir>
  16.        Directory to begin at. If not specified, the current directory
  17.        is assumed, unless a FROM file is specified.
  18.  
  19.      FROM <file>
  20.        Instead of specifying a beginning directory, a file may be
  21.        specified that contains the list of directories to scan.
  22.        This can speed up multiple calls to the same directory tree
  23.        by specifying an output file with the DIRLIST qualifier, then
  24.        on successive calls to TREE using that file as the FROM file.
  25.        This eliminates the directory scan phase on later calls.
  26.  
  27.      PAT <pat>
  28.        ARP/AmigaDOS pattern to match. All directories in the tree are
  29.        checked, reguardless of whether they match the supplied pattern.
  30.  
  31.      DIRS,FILES
  32.        Select based on file type. If neither specified, both files and
  33.        directories are listed.
  34.  
  35.      SORT
  36.        Sort output by directory and filename. All files are listed
  37.        before the files in sub-directories. This qualifier does not
  38.        control sorting of the directory file. It is always sorted.
  39.  
  40.      BEFORE | UPTO, AFTER | SINCE <date>
  41.        Select based on date of file. <date> is in format expected by
  42.        the DOS LIST command, although the "/" character may be used
  43.        in place of the dash ("-").
  44.  
  45.      FLAGS <flags>
  46.        Select based on protection code. <flags> is list of flags that
  47.        must be set or cleared. If the flag is lowercase, that flag
  48.        must be set. If the flag is uppercase, that flag must be
  49.        cleared. If absent, the flag is not checked.
  50.  
  51.      MIN,MAX <number>
  52.        Select based on file size. Minimum and/or maximum size of file
  53.        in bytes. Not good to use if only selecting directories.
  54.  
  55.      [NO]COMMENTS
  56.        Select based on the presence or absence of a comment. You
  57.        cannot specify both COMMENTS and NOCOMMENTS.
  58.  
  59.      MACRO <name>
  60.        Name of an Arexx macro. This macro will be called only if all the
  61.        other tests pass. The macro is assumed to be in the REXX: directory,
  62.        with a file extension of ".tree". The parameters passed are
  63.        (<filename>, <type>, <bytes>, <blocks>, <protection-flags>, <days>,
  64.        <minutes>, <ticks>, <comment>). The macro MUST return a string value
  65.        which, if not null, is written to the output instead of the filename.
  66.        Of course, the macro may DO something to the file, in which case the
  67.        return value can act as a "quiet" or "verbose" switch.
  68.  
  69.      TO <file>
  70.        Send output to indicated file instead of STDOUT. This does NOT
  71.        include direct output from the MACRO, if specified.
  72.  
  73.      DIRLIST <file>
  74.        Normally, a temporary file is created that holds the list of
  75.        directories in the tree, and deleted at the end. This file can
  76.        be saved using this qualifier and supplying the name of the file
  77.        to contain the list. The directory list is only sorted if the
  78.        SORT qualifier is also present. See the FROM qualifier description.
  79.  
  80. */
  81.  
  82. /*
  83. TREE DIR,FROM/K,P=PAT/K,DIRS/S,FILES/S,SORT/S,AFTER=SINCE/K,BEFORE=UPTO/K,
  84.      FLAGS/K,MIN/K,MAX/K,COMMENTS/S,NOCOMMENTS/S,MACRO/K,TO/K,DIRLIST/K
  85. */
  86.  
  87. /* External routines: DirIndex.rexx */
  88.  
  89. signal on failure; signal on break_c
  90. options failat 10
  91. call addlib 'rexxextra.library',-20,-30,0
  92.  
  93. facility = 'Tree'
  94. retcode = 0
  95.  
  96. template = ,
  97.      'DIRS/S,FILES/S,SORT/S,COMMENTS/S,NOCOMMENTS/S,FROM/K,TO/K,P=PAT/K,' || ,
  98.      'AFTER=SINCE/K,BEFORE=UPTO/K,FLAGS/K,MIN/K,MAX/K,MACRO/K,' || ,
  99.      'DIRLIST/K,DIR'
  100. dtemplate = 'DIR,FROM/K,DIRLIST/K,TO/K,P=PAT/K,DIRS/S,FILES/S,SORT/S,' || ,
  101.         'AFTER=SINCE/K,BEFORE=UPTO/K,FLAGS/K,MIN/K,MAX/K,' || ,
  102.         'COMMENTS/S,NOCOMMENTS/S,MACRO/K'
  103. args. = ''
  104. tmpfile = 't:TREE.'||pragma('ID'); args.DIRLIST = tmpfile'.1'
  105.  
  106. parse value 'TREETMPFILE STDOUT 1 0 10000000 0 1' with ,
  107.   inhandle outhandle j args.MIN args.MAX nfl simple ,
  108.   . listcmd args.DIR args.TO args.FROM args.MACRO simplecmd
  109.  
  110. parse arg g_c
  111. do while g_c='?'
  112.   options prompt dtemplate': '  /* this template is      */
  113.   parse pull g_c        /* displayed to the user */
  114.   if g_c='?' then do
  115.     g_s=sourceline(3)
  116.     if pos('/*',g_s)=0 then break; if pos('*/',g_s)>0 then break
  117.     say
  118.     g_s=sourceline(4)
  119.     do i=5 while pos('*/',g_s)=0; say g_s; g_s=sourceline(i); end
  120.     say
  121.     end
  122.   end
  123. interpret Cparse(g_c,template,'args')
  124. if args.ERRCODE > 1 then do; say facility'-E-BADARGS,' args.ERRTEXT; exit 5; end
  125.  
  126. if args.AFTER ~= '' then
  127.   listcmd = listcmd 'SINCE ' || translate(args.AFTER,'-','/')
  128. if args.BEFORE ~= '' then
  129.   listcmd = listcmd 'UPTO ' || translate(args.BEFORE,'-','/')
  130. if args.P ~= '' then
  131.   listcmd = listcmd 'PAT "' || args.P || '"'
  132. if args.DIRS then listcmd = listcmd 'DIRS'
  133. if args.SORT then listcmd = listcmd 'SORT'
  134. if args.FILES then listcmd = listcmd 'FILES'
  135. if args.MACRO ~= '' then do
  136.   args.MACRO = fparse(pragma('D'),args.MACRO,'REXX:.tree')
  137.   simple = 0
  138.   end
  139. if args.FLAGS ~= '' then do
  140.   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 .
  141.   nfl = length(args.FLAGS)
  142.   simple = 0
  143.   end
  144. if (args.MIN > 0) | (args.MAX < 10000000) then simple = 0
  145.  
  146. /* simple check of input for validity */
  147. if (args.COMMENTS & args.NOCOMMENTS) then
  148.   call sayerror("Can't specify both 'COMMENTS' and 'NOCOMMENTS'")
  149.  
  150. if ~datatype(args.MIN,'N')  | ~datatype(args.MAX,'N') then
  151.   call sayerror("MIN and/or MAX value must be numeric")
  152.  
  153. if (args.MIN > args.MAX) then call sayerror("MIN can't be more than MAX")
  154.  
  155. if (args.FROM ~= '' & args.DIR ~= '') then
  156.   call sayerror("Can't have both a FROM file and a DIR")
  157.  
  158. if args.FROM ~= '' then args.DIRLIST = args.FROM
  159. else do
  160.   if args.DIR = '' then args.DIR = pragma('D')        /* default is current */
  161.   if ~exists(args.DIR) then call sayerror(args.DIR' does not exist')
  162.   'DirIndex' args.DIR args.DIRLIST                    /* make list of dirs  */
  163.   end
  164. if args.TO ~= '' then
  165.   if simple then do
  166.     simplecmd = '>>'args.TO
  167.     if exists(args.TO) then call delete args.TO
  168.     else nop
  169.     end
  170.   else if open('OUTFILE',args.TO,'w') then outhandle = 'OUTFILE'
  171.   else exit 20
  172. if ~simple then simplecmd = 'TO' tmpfile
  173. 'ExecIO read' args.DIRLIST 'stem dirs.'
  174. /*
  175.     Main Loop
  176. */
  177. do jj = 1 to dirs.0
  178.   pdir = dirs.jj
  179.   if word(statef(pdir),1) = 'DIR' then do
  180.     'LIST' simplecmd listcmd 'LFORMAT="%S%S" "'pdir'"'
  181.     if ~simple then do
  182.       if ~open(inhandle,tmpfile,'r') then exit 20
  183.       pfile = readln(inhandle)
  184.       do j = 1 while ~eof(inhandle)
  185.     parse value statef(pfile) with type bytes blocks proflags days minutes ticks comment
  186.     if datatype(ticks,'N') then do
  187.       comment = substr(comment,2)
  188.       pflags = upper(compress(proflags,'-'))
  189.       ok = 1 /* assume the file will pass our tests */
  190.       if (bytes < args.MIN) | (bytes > args.MAX) | (args.COMMENTS & comment = '') | ,
  191.          (args.NOCOMMENTS & comment ~= '') then ok = 0
  192.       else do i = 1 to nfl
  193.         if (pos(fl.i,'hsparwed') > 0) & (pos(upper(fl.i),pflags) = 0) then ok = 0
  194.         else if (pos(fl.i,'HSPARWED') > 0) & (pos(fl.i,pflags) > 0) then ok = 0
  195.         end i
  196.       if ok & (args.MACRO ~= '') then do
  197.         interpret 'mr = "'args.MACRO'"(pfile,' || ,
  198.         'type,bytes,blocks,proflags,days,minutes,ticks,comment)'
  199.         if mr = '' then ok = 0; else pfile = mr
  200.         end
  201.       if ok then call writeln outhandle, pfile
  202.       end
  203.     pfile = readln(inhandle)
  204.     end j
  205.       call close inhandle
  206.       end
  207.     end
  208.   end jj
  209.  
  210. GetOut:
  211. if outhandle ~= 'STDOUT' then call close outhandle
  212. 'Delete' tmpfile'(%|.?) quiet'
  213. exit retcode
  214.  
  215. break_c:
  216. break_d:
  217. break_e:
  218. break_f:
  219.   say facility'-E-BREAK, Control-C interrupt'
  220.   exit 20
  221. failure:
  222.   say facility'-E-FAIL, Line:' sigl', Error:' rc; retcode = rc; signal GetOut
  223. syntax:
  224.   say facility'-E-SYNTAX, Line:' sigl', Error:' rc; retcode = rc; signal GetOut
  225. error:
  226.   say facility'-E-ERROR, Line:' sigl', Error:' rc; retcode = rc; signal GetOut
  227.  
  228. sayerror: procedure expose facility
  229.   parse arg x
  230.   say facility'-E-ERROR,' x
  231.   retcode = 10
  232.   signal GetOut
  233.  
  234.