home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 18 REXX / 18-REXX.zip / drtree.zip / DIRMATCH.CMD next >
OS/2 REXX Batch file  |  1994-02-17  |  14KB  |  296 lines

  1. /*  Program DIRMATCH.CMD rev 1.0 1/1/94 by Conrad W. Clark 70544,760 */
  2. /*  you are licensed to use, copy, and redistribute as long */
  3. /*  as the 1st 5 lines of this file remain as is, and you and */
  4. /*  subsequent licensees agree that this program is distributed */
  5. /*  as is, use and consequences are solely the responsibility of the user. */
  6. /*  rexx pgm to find file name matches in  two directory or subdir structures */
  7. /*  the program is useful for finding obsolete DLLs, or mislaid or duplicate programs  */
  8. /*  This program is distributed as is, use and consequences are solely the responsibility */
  9. /*  of the user. */
  10. /*  Developed and tested under OS/2 2.1.  It should work with OS/2 2.0 */
  11. /*  */
  12. /*  Use of Program:  */
  13. /*  [d:\]dirmatch[.cmd] filestructure targetstructure [prn:|stdout:|filename] [string]*/
  14. /*    dirmatch ?  displays online help */
  15. /*  for example, if dirmatch.cmd is in e:\cmd,                                 */
  16. /*  */
  17. /*      e:\cmd\dirmatch c:\os2\dll\*.* c:\describe\dll\*.* will find files with matching */
  18. /*      names in the dll directories, and their subdirectories, and display matching pairs  */
  19. /*  */
  20. /*      e:\cmd\dirmatch c:\os2\dll\*.* c:\describe\dll\*.* prn: will find files with matching */
  21. /*      names, display matched pairs, and print target matches  */
  22. /*  */
  23. /*      e:\cmd\dirmatch c:\os2\dll\*.* c:\describe\dll\*.* prn: xyz will find files with matching */
  24. /*      names if they include the string xyz, display matched pairs, and print target matches  */
  25. /*         note that if the 3rd arg is a file, and it exists, it will be appended to.  */
  26. /*         note that if a 4th arg string is specified, you must specify the 3rd arg, since the   */
  27. /*         filter expects to lineout lines in the targetfiles.i containing xyz    */
  28. /*  the use of shell sorted source and targets give much better performance with large */
  29. /*  numbers of files.  for example, a 233 source by 1324 target took 15 mins unsorted, */
  30. /*  170 seconds sorted */
  31. /*  */
  32. /*  insert additional filters or selection logic at the comment INSERT FILTERS HERE */
  33. /*  */
  34. /*  explain variables  */
  35. /*  */
  36. cr = d2c(13)     /*  carriage return */
  37. bs = d2c(8)       /*  backspace */
  38. lf  = d2c(10)     /*  line feed */
  39. /*  filespec is 1st argument, a directory path spec, including wildcards */
  40. /*  targetspec is 2nd argument, a directory path spec, including wildcards */
  41. /*  outfile is optional 3rd argument, on output device or file name */
  42. /*    suggested values prn: for printer, lpt1: for printer, stdout: for display, or a filename */
  43. /*  stringinfile is optional 4th argument, to select only files containing that string */
  44. /*  files.j is an array of file names from SysFileTree, of source files.  */
  45. /*  files.0 is number of files */
  46. /*  targetfiles.i is target file array, similar to files.j */
  47. /*  structime is a timestamp of elapsed time */
  48. /*  numbermatches is number of file matches found, = number of records in 3rd arg's file */
  49. /*  istart is place pointer for target file array */
  50. /*  j is placepointer for source file array */
  51. /*  i is transient index into target file array */
  52. /*  fileposition points to \ just before file name (or : after drive letter in filter) */
  53. /*  sourceflen is length of current source file name (without path info) */
  54. /*  sourcestring and targetstring are the file names (not including path, eg name.dat ) */
  55. /*  matchcorrection is used to back up the target placeholder, to get matches of dups */
  56. /*  linematch.klm is array size in .0 containing lines in target containing stringinfile string */
  57. /*  fullfilename is file name including drive and path for string filter SysFileSearch */
  58. /*  result is a rexx special variable for function return codes, if 0, ok */
  59. /*    for documentation of the shell sort variables, see the referenced textbook */
  60.  
  61. starttime = time('R')                   /* reset elapsed timer */
  62.  
  63. call RxFuncAdd 'SysLoadFuncs', 'RexxUtil', 'SysLoadFuncs' /* register all utility functions */
  64. call SysLoadFuncs
  65. filespec = ''           /*  initialize args to null strings */
  66. targetspec = ''
  67. outfile = ''
  68. stringinfile = ''
  69. arg filespec  targetspec outfile stringinfile    /* get the two structures to match */
  70.                                                      /* outfile is optional file or printer name */
  71.                                                      /* for list of target files matching */
  72.                                 /* stringinfile is a string, select only targets containing it */
  73. if filespec = '' then
  74. do
  75.         say 'ERROR, missing source directory structure'
  76.         exit
  77. end
  78.  
  79. if filespec = '?'  then        /* display online help */
  80. do
  81. say 'Program DIRMATCH.CMD rev 1.0 1/1/94 by Conrad W. Clark 70544,760'
  82. say 'A rexx pgm to find file name matches in  two directory or subdir structures,'
  83. say 'useful for finding obsolete DLLs, or mislaid or duplicate programs.'
  84. say ' '
  85. say ' Use of Program:'
  86. say ' [d:\]dirmatch[.cmd] filestruct targetstruct [prn:|stdout:|filename] [string]'
  87. say ' '
  88. say ' for example, if dirmatch.cmd is in e:\cmd,'
  89. say '   e:\cmd\dirmatch c:\os2\dll\*.* c:\describe\dll\*.* will find files'
  90. say '     with matching names in the dll directories, and their subdirectories,'
  91. say '     and display matching pairs'
  92. say '   e:\cmd\dirmatch c:\os2\dll\*.* c:\describe\dll\*.* prn: will find files'
  93. say '     with matching names, display matched pairs, and print target matches'
  94. say '   e:\cmd\dirmatch c:\os2\dll\*.* c:\describe\dll\*.* prn: xyz will find files'
  95. say '     with matching names if they include the string xyz, display matched pairs,'
  96. say '     and print target matches'
  97. say ' '
  98. say 'If the 3rd arg is a file, and it already exists, it will be appended to.'
  99. say 'Note that if a 4th arg string is specified, you must specify the 3rd arg,'
  100. say 'since the filter expects to lineout lines in the targetfiles.i containing xyz.'
  101. say 'Internal shell sorts improve performance with numerous files.'
  102. exit
  103. end
  104.  
  105. if targetspec = '' then
  106. do
  107.         say 'ERROR, missing target directory structure'
  108.         exit
  109. end
  110.  
  111. say 'filespec is' filespec
  112.  
  113. call SysFileTree filespec, 'files.', 'sf'    /* get files in first dir structure */
  114.                                                             /* including subdirectories */
  115. if result <> 0  then
  116. do
  117.         say 'source file ERROR, SysFileTree result = ' result
  118.         say 'result 2 is not enough memory'
  119.         exit
  120. end
  121. say 'number input files is ' files.0
  122. say 'match to target filespec'
  123. say 'target is  ' targetspec 
  124. call charout cr||lf
  125.  
  126. call SysFileTree targetspec, 'targetfiles.', 'sf'    /* get files in target dir structure */
  127. if result <> 0  then
  128. do
  129.         say 'target file ERROR, SysFileTree result = ' result
  130.         say 'result 2 is not enough memory'
  131.         exit
  132. end
  133.  
  134. say 'number target files is ' targetfiles.0
  135. structime = time('E')
  136. say 'get structures timestamp = ' structime
  137.  
  138. call sortfiles                             /*  sort input files  */
  139. call sorttargets                        /*  sort target files  */
  140.  
  141. call charout 'stdout:', cr
  142.  
  143. numbermatches = 0                    /* to say how many matched */
  144. istart = 1                              /* initially, start at start of targets */
  145.                                         /* files. and targetfiles. are sorted ascending */
  146. do j = 1 to files.0                      /* for each file, compare to remaining target files */
  147.     fileposition = lastpos('\',files.j)    /* last \ is just before file name */
  148.     sourceflen = length(files.j) - fileposition
  149.     sourcestring = right(files.j, sourceflen)
  150.     call charout "stdout:", sourcestring  /* say file.j as heartbeat */
  151.     gotmatch = 0
  152.     matchcorrection = 0                   /* correct for dups in files. */
  153.  
  154.         do i = istart to targetfiles.0
  155.            fileposition = lastpos('\',targetfiles.i)
  156.            targetstring = right(targetfiles.i,(length(targetfiles.i)-fileposition))
  157.            if sourcestring = targetstring  then  /* matching filenames */
  158.                   do ilinematch = 1     /*  counter for leaving if no string match */
  159.                         call charout "stdout:",cr||lf
  160. /*  INSERT FILTERS HERE */
  161. /*  string match filter (not case sensitive) */
  162.                         if stringinfile <>'' then     /*  if a string to find is specified */
  163.                                 /* accept target if it contains 4th arg string */
  164.                           do
  165.                           gotmatch = 1            /*  got output, do not backspace */
  166.                           fileposition = lastpos(':',targetfiles.i)  /* -> : after drive letter */
  167.                         /*  get file name including drive and path */
  168.                           fullfilename = right(targetfiles.i,(length(targetfiles.i)-fileposition + 2))
  169.                           call SysFileSearch stringinfile, fullfilename, linematch
  170.                              if result <> 0  then
  171.                                 do
  172.                                        say 'source file ERROR, SysFileSearch result = ' result
  173.                                        say 'result 2 is not enough memory'
  174.                                        say 'result 3 is error opening file'
  175.                                        exit
  176.                                 end
  177.                              if linematch.0 = 0 then leave ilinematch  /* no string match */
  178.                              do klm = 1 to linematch.0  /*  print lines with string match */
  179.                               do
  180.                                 call lineout outfile, linematch.klm
  181.                                    if result <> 0  then
  182.                                    do
  183.                                        say 'source file ERROR, lineout result = ' result
  184.                                        say 'check 3rd argument, printer status, file name'
  185.                                        exit
  186.                                    end
  187.                               end
  188.                              end
  189.                           end
  190. /*  end string match filter */
  191.                         say 'file is   ' files.j
  192.                         say 'target is ' targetfiles.i
  193.                         numbermatches = numbermatches + 1
  194.                         matchcorrection = matchcorrection + 1
  195.                    /*  if a third argument, output target line to file or printer (prn:) */
  196.                         if outfile <> ''  then
  197.                                 do
  198.                                    call lineout outfile, targetfiles.i
  199.                                    if result <> 0  then
  200.                                    do
  201.                                        say 'source file ERROR, lineout result = ' result
  202.                                        say 'check 3rd argument, printer status, file name'
  203.                                        exit
  204.                                     end
  205.                                 end
  206.                         gotmatch = 1            /*  got output, do not backspace */
  207.                 leave ilinematch        /* must explicitly leave if dummy loop variable */
  208.                 end
  209.         if sourcestring < targetstring then
  210.                 do
  211.                    istart = i - matchcorrection  /* recheck in case of dups in files. */
  212.                    leave i             /* do not recheck if too small */
  213.                 end
  214.         end
  215.     if gotmatch = 0 then                          /* maintain heartbeat */
  216.     do
  217.       call charout "stdout:",bs
  218.       do k = 1 to (sourceflen - 1)               /*reposition cursor at start of heartbeat */
  219.          call charout 'stdout:', ' '||bs||bs
  220.       end
  221.     call charout "stdout:",' '||bs
  222.     end
  223. end
  224. endtime = time('E')
  225. say 'get structures timestamp = ' structime
  226. say 'sort input files timestamp = ' sortintime
  227. say 'sort target files timestamp = ' sorttartime
  228. say 'completion timestamp = ' endtime
  229. say 'number of matches = ' numbermatches
  230. exit
  231.  
  232. /**********************/
  233. /*                           */
  234. /*  SORT ROUTINES       */
  235. /*                           */
  236. /**********************/
  237. sortfiles:                      /* shell sort of input files */
  238.                                 /* use shell sort (Sedgewick:Algorithms 1984) */
  239.                                 /* since many directories may be already ordered */
  240. h = 1
  241. do until h>files.0
  242.   h = 3*h+1
  243. end /* do */
  244. do forever until h = 1 
  245.   h = h % 3               /* integer result */
  246.   do i = h+1 to files.0
  247.     v = files.i
  248.     fileposition = lastpos('\',files.i)+1  /* last \ is just before file name */
  249.     j = i
  250.     k = j-h
  251.     key1 = substr(v,fileposition)
  252. /* say 'key1 = ' key1 */
  253.     do while substr(files.k,(lastpos('\',files.k)+1)) > key1
  254.           files.j = files.k
  255.           j = j-h
  256.           k = j-h
  257.           if j <= h then leave
  258.      end
  259.   files.j = v
  260.   end /* do */
  261. end /* do forever */
  262. sortintime = time('E')
  263. say 'sort input files timestamp = ' sortintime
  264. return
  265.  
  266.  
  267.  
  268. sorttargets:                /*  shell sort target files  */
  269.                                /* use shell sort (Sedgewick:Algorithms 1984) */
  270.                                 /* since many directories may be already ordered */
  271. h = 1
  272. do until h>targetfiles.0
  273.   h = 3*h+1
  274. end /* do */
  275. do forever until h = 1
  276.   h = h % 3               /* integer result */
  277.   do i = h+1 to targetfiles.0
  278.     v = targetfiles.i
  279.     j = i
  280.     k = j-h
  281.     fileposition = lastpos('\',targetfiles.i)+1  /* last \ is just before file name */
  282.     key1 = substr(v,fileposition)
  283. /* say 'key1 = ' key1 */
  284.     do while substr(targetfiles.k,(lastpos('\',targetfiles.k)+1)) > key1
  285.           targetfiles.j = targetfiles.k
  286.           j = j-h
  287.           k = j-h
  288.           if j <= h then leave
  289.      end
  290.   targetfiles.j = v
  291.   end /* do */
  292. end /* do forever */
  293. sorttartime = time('E')
  294. say 'sort target files timestamp = ' sorttartime
  295. return
  296.