home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 9 Archive / 09-Archive.zip / zipdel.zip / zipdel.cmd next >
OS/2 REXX Batch file  |  1997-03-18  |  11KB  |  374 lines

  1. /*----------------------------------------------------------------------*\
  2.     zipdel.cmd      -- delete files that were unpacked from zip or tar files
  3.  
  4.     Wonkoo Kim (wkim+@pitt.edu)
  5.  
  6.     Use this script when you don't want to update an archive (zip or tar)
  7.     file but want to delete files on disk only if they have the same
  8.     timestamp / size / subdir structure as the files in the archive,
  9.     while keeping modified files (of different time or size) on disk.
  10.  
  11.     Supported archive files are .zip, .tar, .tar.gz, .tgz (gzipped tar), tar.Z.
  12.  
  13.  
  14.     This script requires the following programs in PATH:
  15.     Info-Zip's unzip.exe (for zip files)
  16.     GNU tar.exe (for tar files)
  17.     sort.exe of OS/2 (To use GNU sort, change 'sort /r' to 'sort -r' below.)
  18.  
  19.  
  20.     History:
  21.     April 25, 1995        The first version.
  22.     August 11, 1995     Fixed bug when file name had special symbols.
  23.     August 18, 1995     Fixed bug: compute with size of actual files
  24.                 instead of file size info from .zip contents
  25.     August 25, 1995     Added delete option for Read-Only files.
  26.     December 25, 1995   Now more reliably deletes empty dirs.
  27.     May 4, 1996        Detects delete error
  28.     July 5, 1996        Enhanced a bit by using rxqueue,
  29.                 Added GNU tar file (.tar, .tar.gz, .tgz) support.
  30.     March 18, 1997        Fixed bug when file name had '%' characters.
  31.                 (CMD shell converts double '%%' to single '%'.)
  32. \*----------------------------------------------------------------------*/
  33.  
  34. '@echo off'
  35.  
  36. Call RxFuncAdd 'SysLoadFuncs', 'RexxUtil', 'SysLoadFuncs'
  37. Call SysLoadFuncs
  38.  
  39. parse arg args
  40.  
  41. subdir = ''
  42. force = 0
  43. junk = 0
  44. quiet = 0
  45. readonly = 0
  46.  
  47. cmdargs = ''
  48. do i=1 to words(args)
  49.     opt = word(args, i)
  50.  
  51.     select
  52.     when left(opt, 2) = '-?' then
  53.     leave i
  54.     when left(opt, 2) = '-f' then
  55.     force = 1
  56.     when left(opt, 2) = '-j' then
  57.     junk = 1
  58.     when left(opt, 2) = '-d' then
  59.     do
  60.         subdir = substr(opt,3)
  61.         if subdir = '' then do
  62.         i = i + 1
  63.         subdir = word(args, i)
  64.         end
  65.     end
  66.     when left(opt, 2) = '-q' then
  67.     do
  68.         quiet = quiet + 1
  69.         if substr(opt,3) = 'q' then quiet = quiet + 1
  70.     end
  71.     when left(opt, 2) = '-r' then
  72.     readonly = 1
  73.     otherwise
  74.     if cmdargs = '' then
  75.         cmdargs = opt
  76.     else
  77.         cmdargs = cmdargs||' '||opt
  78.     end
  79. end
  80.  
  81. if cmdargs = '' | left(opt, 2) = '-?' then do
  82.     say
  83.     say 'Usage: zipdel [-option] [zip or tar archive files]'
  84.     say
  85.     say 'Options:'
  86.     say '   -?          This help screen'
  87.     say '   -d subdir   files to be deleted are under "subdir" tree'
  88.     say '   -f          force to delete even if size and time stamp are different'
  89.     say '   -j          Junk (don''t use) directory info of archive file'
  90.     say '   -q[q]       Quiet mode (default mode is verbose); -qq means quieter'
  91.     say '   -r          Delete Read-Only files as well'
  92.     say 'Archive files: *.zip, *.tar, *.tar.gz, *.tgz, *.tar.Z'
  93.     say
  94.     say 'Description:'
  95.     say '   ZIPDEL will delete any file that has the same time stamp & size and'
  96.     say '   that is under the same subdir as the one contained in zip or tar file.'
  97.     /**
  98.     say '   If -j option is used, ZIPDEL will look at current dir for all files'
  99.     say '   by disregarding subdir info of files in zip or tar archive file.'
  100.     **/
  101.     say '   The zip or tar archive file is safe (untouched) from this operation.'
  102.     say
  103.     say "WARNING:  Though the chance of failure is very rare, still it's not perfect."
  104.     say "   This program checks file's time stamp only up to minutes, not seconds,"
  105.     say '   thus can be fooled by such slight time stamp differences.'
  106.     say '   Also file contents are not compared but only size, so be careful!'
  107.     say
  108.     say 'Wonkoo Kim (wkim+@pitt.edu)'
  109.     exit
  110. end
  111.  
  112. if (subdir \= '') & (right(subdir,1) \= ':') then
  113. do
  114.     subdir = translate(subdir,'\','/')
  115.     subdir = strip(subdir, 't', '\')||'\'
  116. end
  117.  
  118. tmpfile = SysTempFileName('zipdel.???')
  119.  
  120. do i=1 to words(cmdargs)
  121.     archive = word(cmdargs, i)
  122.     if exists(archive) then
  123.     do
  124.     if quiet < 2 then do
  125.         say
  126.         say 'Source Archive:' archive
  127.     end
  128.  
  129.     fname = filespec('name', archive)
  130.     fl = lowercase(fname)
  131.     select
  132.     when right(fl,4) = '.zip' | right(fl,4) = '.exe' then do
  133.         /* to include self-extraction .exe zip file */
  134.         if zipprog = 'ZIPPROG' then do
  135.         zipprog = SysSearchPath('PATH', 'unzip.exe')
  136.         if zipprog = '' then do
  137.             say "**ERROR: zip.exe is not found in PATH. (Get Info-Zip's zip.exe.)"
  138.             exit 1
  139.         end
  140.         end
  141.         'unzip -Z' archive '2> nul | rxqueue'
  142.         zip = 1
  143.         end
  144.     when (right(fl,7) = '.tar.gz' | right(fl,6) = '.tar.z',
  145.                       | right(fl,4) = '.tgz') then do
  146.         if tarprog = 'TARPROG' then do
  147.         tarprog = SysSearchPath('PATH', 'tar.exe')
  148.         if tarprog = '' then do
  149.             say "**ERROR: tar.exe is not found in PATH. (Get GNU tar.)"
  150.             exit 1
  151.         end
  152.         end
  153.         'tar -ztvf' archive '2> nul | rxqueue'
  154.         zip = 0
  155.         end
  156.     when right(fl,4) = '.tar' then do
  157.         if tarprog = 'TARPROG' then do
  158.         tarprog = SysSearchPath('PATH', 'tar.exe')
  159.         if tarprog = '' then do
  160.             say "**ERROR: tar.exe is not found in PATH. (Get GNU tar.)"
  161.             exit 1
  162.         end
  163.         end
  164.         'tar -tvf' archive '2> nul | rxqueue'
  165.         zip = 0
  166.         end
  167.     otherwise
  168.         /* say ' **Unsupported: ' file */
  169.         iterate
  170.     end
  171.  
  172.     deleted_files = 0
  173.     deleted_bytes = 0
  174.     notdel_files = 0
  175.     notdel_bytes = 0
  176.     delerr_files = 0
  177.     delerr_bytes = 0
  178.     not_found = 0
  179.     nf_bytes = 0
  180.     rmdirs = 0
  181.     nrmdirs = 0
  182.     prevpath = ''
  183.     do while queued() <> 0
  184.         parse pull list
  185.         file = translate( subword(list, 8+zip), '\', '/')
  186.         path = strip( filespec("path", file), 'T', '\')
  187.         if (junk) then do
  188.         file = filespec("name", file)
  189.         path = ''
  190.         end
  191.         if left(list, 1) = '-' then
  192.         do
  193.         size = word(list, 3+zip)
  194.         if zip = 1 then do    /* zip file list */
  195.             date = right( word(list, 7), 9, '0')
  196.             time = word(list, 8)
  197.             end
  198.         else do         /* tar file list */
  199.             date = right(word(list,5),2,'0')'-'word(list,4)'-'right(word(list,7),2)
  200.             time = word(list, 6)
  201.             end
  202.         stamp = date||' '||time
  203.         file = subdir||file
  204.         if exists(file) then
  205.         do
  206.             fbytes = fsize(file)
  207.             fstamp = left(fasctime(file),9)||right(fbytes, 9)
  208.             if ( ( left(fasctime(file),length(stamp)) = stamp &,
  209.                             fbytes = size ) | force) then
  210.             do
  211.             if readonly = 1 then
  212.                 call SysFileTree file, 'ff', , , '**---'    /* remove attrib */
  213.             rc = SysFileDelete(file)
  214.             if (rc = 0) then do
  215.                 if quiet=0 then say ' Deleted: ' fstamp file
  216.                 deleted_files = deleted_files + 1
  217.                 deleted_bytes = deleted_bytes + fbytes
  218.             end
  219.             else do
  220.                 if quiet<=1 then say ' ** Delete Error:' fstamp file
  221.                 delerr_files = delerr_files + 1
  222.                 delerr_bytes = delerr_bytes + fbytes
  223.                 notdel_files = notdel_files + 1
  224.                 notdel_bytes = notdel_bytes + fbytes
  225.             end
  226.             end
  227.             else do
  228.             if quiet<=1 then say ' ** Not Deleted:' fstamp file
  229.             notdel_files = notdel_files + 1
  230.             notdel_bytes = notdel_bytes + fbytes
  231.             end
  232.         end
  233.         else do
  234.             if quiet = 0 then say ' ** Not Found:' file
  235.             not_found = not_found + 1
  236.             nf_bytes = nf_bytes + size
  237.         end
  238.         end
  239.         /*
  240.          * save a list of subdir names (to delete empty dirs)
  241.          */
  242.         if path \= prevpath then do
  243.         rc = lineout(tmpfile, subdir||path)
  244.         if rc \= 0 then do
  245.             say '**ERROR: lineout()' tmpfile
  246.             exit 1
  247.         end
  248.         pathtoken = translate(path, ' ', '\')
  249.         do j = words(pathtoken) to 1 by -1
  250.             k = wordindex(pathtoken, j) - 1
  251.             if k > 0 then k = k - 1
  252.             if left(path, k) == left(prevpath, k) then
  253.             leave j
  254.             rc = lineout(tmpfile, subdir||left(path,k))
  255.         end
  256.         prevpath = path
  257.         end
  258.     end
  259.  
  260.     if exists(tmpfile) then do
  261.         call stream tmpfile, 'C', 'CLOSE'
  262.         'sort /r <' tmpfile '2> nul | rxqueue'
  263.  
  264.         if quiet < 2 & \junk then do
  265.         say
  266.         say ' Purging Empty Directories ...'
  267.         end
  268.         path = ''
  269.         do while queued() <> 0
  270.         parse pull input
  271.         if input \= '' & input \= path then do
  272.             path = input
  273.             rc = SysRmDir(path)
  274.             if rc = 0 then do
  275.             say '  Removed:  ' path||'\'
  276.             rmdirs = rmdirs + 1
  277.             end
  278.             if rc \= 0 & rc \= 3 & quiet < 2 then do
  279.             say '  Non-empty:' path
  280.             nrmdirs = nrmdirs + 1
  281.             end
  282.         end
  283.         end
  284.         call stream tmpfile, 'C', 'CLOSE'
  285.         call SysFileDelete tmpfile
  286.     end
  287.  
  288.     if quiet < 2 then do
  289.         len = max(length(deleted_bytes), length(notdel_bytes), length(nf_bytes))
  290.         say
  291.         say ' Result:'
  292.         if (deleted_files > 0) then
  293.         say '  Deleted:    ' format(deleted_files,4) 'files (',
  294.             || right(commas(deleted_bytes),len+2) 'bytes)'
  295.         if (notdel_files > 0) then
  296.         say '  Not Deleted:' format(notdel_files,4) 'files (',
  297.             || right(commas(notdel_bytes),len+2) 'bytes)'
  298.         if (delerr_files > 0) then
  299.         say '   (Del Error:' format(delerr_files,4) 'files (',
  300.             || right(commas(delerr_bytes),len+2) 'bytes))'
  301.         if (not_found > 0) then
  302.         say '  Not Found:  ' format(not_found,4) 'files (',
  303.             || right(commas(nf_bytes),len+2) 'bytes)'
  304.         if (rmdirs > 0) then
  305.         say '  Removed:    ' format(rmdirs,4) 'dirs.'
  306.         if (nrmdirs > 0) then
  307.         say '  Not Removed:' format(nrmdirs,4) 'dirs.'
  308.     end
  309.     end
  310. end
  311.  
  312. exit 0
  313.  
  314. /*----------------------------------------------------------------------*/
  315. exists: procedure
  316.     arg fname
  317. /*----------------------------------------------------------------------*/
  318. /* check if a file exists.
  319. */
  320.     return stream(fname, 'C', 'QUERY EXISTS') \= ''
  321.  
  322. /*----------------------------------------------------------------------*/
  323. fsize: procedure
  324.     arg fname
  325. /*----------------------------------------------------------------------*/
  326. /* get file size */
  327.     return stream(fname, 'C', 'QUERY SIZE')
  328.  
  329. /*----------------------------------------------------------------------*/
  330. fasctime: procedure
  331.     arg fname
  332. /*----------------------------------------------------------------------*/
  333. /* convert datetime into more readable date string without time part.
  334.  * input argument format is based on getftime().
  335.  */
  336.     datetime = space( stream(fname, 'C', 'QUERY DATETIME'), 1)
  337.     parse var datetime month'-'day'-'year time
  338.     month.01 = 'Jan'
  339.     month.02 = 'Feb'
  340.     month.03 = 'Mar'
  341.     month.04 = 'Apr'
  342.     month.05 = 'May'
  343.     month.06 = 'Jun'
  344.     month.07 = 'Jul'
  345.     month.08 = 'Aug'
  346.     month.09 = 'Sep'
  347.     month.10 = 'Oct'
  348.     month.11 = 'Nov'
  349.     month.12 = 'Dec'
  350.     return day'-'month.month'-'year time
  351.  
  352. /*----------------------------------------------------------------------*/
  353. commas: procedure
  354.     arg number
  355. /*----------------------------------------------------------------------*/
  356. /* insert thousand commas in a positive number string */
  357.     str = number
  358.     p = length(trunc(number))
  359.     do while p > 3
  360.     p = p - 3
  361.     str = insert(',', str, p)
  362.     end
  363.     return str
  364.  
  365. /*----------------------------------------------------------------------*/
  366. lowercase: procedure
  367. /*----------------------------------------------------------------------*/
  368. /* change to lowercase
  369.  */
  370.     arg str
  371.     return translate(str,xrange('a','z'),xrange('A','Z'))
  372.  
  373. /* End of zipdel.cmd */
  374.