home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 18 REXX / 18-REXX.zip / cmdpk164.zip / xren.cmd < prev   
OS/2 REXX Batch file  |  1998-01-10  |  17KB  |  559 lines

  1. /* This is CommandPak's xren command.                   */
  2. /* (w) 1997-98 Ulrich Möller                            */
  3.  
  4. '@echo off'
  5.  
  6. /*  to do: SIMPLE_BACKUP_SUFFIX env var
  7.            "-S" for suffix setting */
  8.  
  9. call RxFuncAdd 'SysLoadFuncs', 'RexxUtil', 'SysLoadFuncs'
  10. call SysLoadFuncs
  11.  
  12. /* The following messages have not yet been moved into XHELPxxx.MSG and will thus
  13.    always be displayed in English. Language support might be added in a later release. */
  14.  
  15. nl = '0d0a'x
  16. err = '<HTML><I>Error in xren:</I> '
  17. errhlp = 'Type <A HREF="">xren -h</A> for help.'
  18. nofilesMsg = err||'File(s) not found. '||errhlp
  19. unknownoptionMsg = err||'Unknown option (<B>-%a</B>). '||errhlp
  20. errorMsg1 = err||'Using these options is not allowed with two file specifications. '||errhlp
  21. errorMsg2 = err||'You must give two file specifications here. '||errhlp
  22. errorMsgFiles = err||'You have not specified any files. '||errhlp
  23. errorMsgTest = err||'The "test" option must be used with other options. '||errhlp
  24. errorMsgForce = err||'The "force" option can only be used when moving files. '||errhlp
  25. errorMsgInteractive = err||'The "interactive" option can presently not be used with the options you have specified. '||errhlp
  26. invwcMsg = err||'Invalid wildcard usage. '||errhlp
  27. checkingMsg = "Checking" /* argument will be added automatically */
  28. procMsg = "Processing" /* argument will be added automatically */
  29. replacedMsg = '  Replaced invalid characters in .LONGNAME:'
  30. longDelMsg = "  .LONGNAME for %a deleted (contained %b)"
  31. skipMsg = '  Skipped deleting .LONGNAME; contains important characters'
  32. inuseMsg = "  Could not remove .LONGNAME for %a; file seems to be in use"
  33. backedupMsg = "    Backed up %a to %b"
  34. renameMsg = "  Renaming %a to %b"
  35. moveMsg = "  Moving %a to %b"
  36. replaceMsg = "    %a exists."nl"      (R)eplace (B)ackup original (S)kip replace_(A)ll? "
  37. interactMsg = "    Is this OK? (Y)es (N)o (A)ll "
  38. dontWorryMsg = "Don't worry, this was test mode only. Nothing was modified."
  39. interruptMsg = "xren was interrupted externally."
  40.  
  41. invalidChars = '\/:*?"<>|,+=[];'
  42.  
  43. signal on halt; trace off
  44.  
  45. parse arg args
  46.  
  47. alwaysReplace = 0
  48. old. = ""
  49. new. = ""
  50. deletelong = 0
  51. realtolong = 0
  52. tolower = 0
  53. toupper = 0
  54. verbose = 0
  55. quiet = 0
  56. test = 0
  57. debug = 0
  58. movealso = 0
  59. force = 0
  60. interactive = 0
  61. backup = 0
  62. FAT = 0
  63.  
  64. /* first process arguments/options */
  65. do while (args \= "")
  66.     parse value args with opt1 args
  67.     if debug then Say "  Parsing" opt1
  68.     if (substr(opt1, 1, 1)="-") | (substr(opt1, 1, 1)="/") then do
  69.         do optcount = 2 to length(opt1) by 1
  70.             optchar = substr(opt1, optcount, 1)
  71.             if debug then Say "    Subparsing" optchar
  72.             select
  73.                 when (optchar="D") then do
  74.                     Say "Debug messages turned on."
  75.                     debug = 1
  76.                     verbose = 1
  77.                     test = 1
  78.                 end
  79.                 when (optchar="d") then
  80.                     deletelong = 1
  81.                 when (optchar="r") then
  82.                     realtolong = 1
  83.                 when (optchar="t") then do
  84.                     test = 1
  85.                     verbose = 1
  86.                 end
  87.                 when (optchar="8") then
  88.                     FAT = 1
  89.                 when (optchar="b") then do
  90.                     backup = 1
  91.                     interactive = 0
  92.                     force = 0
  93.                 end
  94.                 when (optchar="f") then do
  95.                     force = 1
  96.                     interactive = 0
  97.                     backup = 0
  98.                 end
  99.                 when (optchar="i") then do
  100.                     interactive = 1
  101.                     force=0
  102.                 end
  103.                 when (optchar="L") then do
  104.                     tolower = 1
  105.                     toupper = 0
  106.                     realtolong = 0
  107.                 end
  108.                 when (optchar="U") then do
  109.                     toupper = 1
  110.                     tolower = 0
  111.                     realtolong = 0
  112.                 end
  113.                 when (optchar="v") then do
  114.                     verbose = 1
  115.                     quiet = 0
  116.                 end
  117.                 when (optchar="q") then do
  118.                     quiet = 1
  119.                     verbose = 0
  120.                 end
  121.                 when (optchar="h") | (optchar = "?") then do
  122.                     'call xhelp xren'
  123.                     exit
  124.                 end
  125.                 when (optchar="x") then do
  126.                     'call xhelp _xrenexpl'
  127.                     exit
  128.                 end
  129.             otherwise do
  130.                 'call xhelp "'strReplace(unknownoptionMsg, "%a", optchar)'"'
  131.                 exit
  132.             end
  133.             end /* select */
  134.         end /* do */
  135.     end /* if */
  136.     else
  137.         if old.complete = "" then
  138.             old.complete = opt1
  139.         else new.complete = opt1
  140. end /* do while */
  141.  
  142. if (old.complete = "") then do
  143.     'call xhelp "'errorMsgFiles'"'
  144.     exit
  145. end
  146.  
  147. /* now collect files */
  148. if debug then
  149.     say "Collecting files"
  150.  
  151. files.0 = 0
  152. curdir = directory()
  153. if (directory(old.complete) \= "") then do
  154.     files.1 = old.complete
  155.     files.0 = 1
  156. end
  157. else if (old.complete = "..") then do
  158.     files.1 = ".."
  159.     files.0 = 1               /* these are funny bugs in SysFileTree */
  160. end
  161. else do
  162.     rc = SysFileTree(old.complete, files, "FO", '*--*-')
  163.                                /* Attribs: 'ADHRS' */
  164.     if debug then Say "  "files.0 "file(s) found"
  165.     if files.0 = 0 then do
  166.         'call xhelp "'nofilesMsg'"'
  167.         exit
  168.     end
  169. end
  170. call directory(curdir)
  171.  
  172. renMode = 0
  173. moveMode = 0
  174. extMode = 0
  175. wildcards = 0
  176.  
  177. if (realtolong) | (tolower) | (toupper) then do
  178.     extMode = 1
  179.     if (interactive) then
  180.         call xhelp '"'errorMsgInteractive'"'
  181. end
  182.  
  183. do
  184.     if debug then say "Entering mode analysis for old.spec"
  185.     old.path = filespec('drive', old.complete)||filespec('path', old.complete)
  186.     old.spec = filespec('name', old.complete)
  187.     if debug then do
  188.         say '  old.path:  "'old.path'"'
  189.         say '  old.spec:  "'old.spec'"'
  190.     end
  191. end
  192.  
  193. if (new.complete \= "") then do
  194.     /* second spec given: seems to be rename/move mode. */
  195.     if debug then say "Entering mode analysis for newspec"
  196.  
  197.     if (new.complete \= "\") & (substr(new.complete, 2) \= ":\") & (right(new.complete, 1) = "\") then new.complete = strip(new.complete, 't', '\')
  198.     curdir = directory()
  199.     if (directory(new.complete) \= "") then do
  200.         /* second spec is dir only --> just move, no rename */
  201.         moveMode = 1
  202.         new.path = new.complete
  203.         renMode = 0
  204.         new.spec = ""
  205.     end
  206.     else do
  207.         new.path = filespec('drive', new.complete)||filespec('path', new.complete)
  208.         new.spec = filespec('name', new.complete)
  209.  
  210.         if (new.path \= "") then do
  211.             moveMode = 1
  212.             if (new.path \= "\") & (substr(new.path, 2) \= ":\") & (right(new.path, 1) = "\") then new.path = strip(new.path, 't', '\')
  213.         end
  214.         if (new.spec \= "") then do
  215.             renMode = 1
  216.         end
  217.         /* second spec is */
  218.     end
  219.     call directory curdir
  220.  
  221.     if debug then do
  222.         if renMode then say "  -> Rename mode enabled; renaming to" new.spec
  223.         if moveMode then say "  -> Move mode enabled; moving to" new.path
  224.         if extMode then say "  -> Extended mode enabled"
  225.     end
  226.  
  227.     if extMode then do
  228.         'call xhelp "'errorMsg1'"'
  229.         exit
  230.     end
  231. end
  232. else
  233.     if (\FAT & \extMode & \deleteLong)then do
  234.         'call xhelp "'errorMsg2'"'
  235.         exit
  236.     end
  237.  
  238. if renMode then do
  239.     /* now evaluate wildcards */
  240.     if (pos('*', new.spec) \= 0) | (pos('?', new.spec) \= 0) then do
  241.             wildcards = 1
  242.             if debug then say "Evaluating wildcards"
  243.             old.wild.pos = pos('*', old.spec)
  244.             new.wild.pos = pos('*', new.spec)
  245.  
  246.             if (old.wild.pos = 1) then
  247.                 if (pos('*', substr(old.spec, old.wild.pos+1)) > 0) then call invwc
  248.                 else if (new.wild.pos = 1) then
  249.                     if (pos('*', substr(new.spec, new.wild.pos+1)) > 0) then call invwc
  250.                     else do
  251.                         old.wild.sub = translate(substr(old.spec, old.wild.pos+1))
  252.                         new.wild.sub = substr(new.spec, new.wild.pos+1)
  253.                     end
  254.                 else call invwc
  255.             else if (old.wild.pos = length(old.spec)) then
  256.                 if (new.wild.pos = length(new.spec)) then do
  257.                     old.wild.sub = translate(substr(old.spec, 1, old.wild.pos-1))
  258.                     new.wild.sub = substr(new.spec, 1, new.wild.pos-1)
  259.                 end
  260.                 else call invwc
  261.             else call invwc
  262.         if debug then do
  263.             say '  old.wild.sub:   "'old.wild.sub'"'
  264.             say '  new.wild.sub:   "'new.wild.sub'"'
  265.         end
  266.     end /* wildcards */
  267. end
  268.  
  269.  
  270. /* now work on file list */
  271. if debug then say "Entering file processing"nl
  272.  
  273. do i = 1 to files.0
  274.     oldName = files.i
  275.     oldnameonly = filespec('name', oldname)
  276.  
  277.     if (realtolong) then do
  278.         rc = SysGetEA(oldname, ".LONGNAME", "longname_")
  279.         longname = substr(longname_, 5)
  280.     end /* this needs to be preserved since deletelong might delete it */
  281.     if (deleteLong) then
  282.         call deleteLongname oldname
  283.  
  284.     /* check which mode we're in */
  285.     select
  286.         when (moveMode) then do    /* move */
  287.             /* first compose new name */
  288.             if renMode then
  289.                 newNameOnly = getNewName(oldname)
  290.             else
  291.                 newNameOnly = filespec('name', oldname)
  292.  
  293.             if (FAT) then
  294.                 newNameOnly = makeFAT(newNameOnly)
  295.  
  296.             if (right(new.path, 1) \= "\") then
  297.                 moveTo = new.path||'\'
  298.             else moveTo = new.path
  299.             newName = moveTo||newNameOnly
  300.  
  301.             /* now check if moving is allowed; confirm if neccessary */
  302.             moveOK = 1
  303.             if (verbose | interactive) then
  304.                 say strReplace(strReplace(moveMsg, '%a', oldname), '%b', newname)
  305.             else if (\quiet) then say oldname
  306.  
  307.             if (stream(newName,'c','query exist') \= "") then do
  308.                 if (force) then
  309.                     'del' newName
  310.                 else if (backup) then
  311.                     call backupFile newName
  312.                 else do
  313.                     resp = queryExists(strReplace(replaceMsg, '%a', newName))
  314.                     if (resp = "R") then
  315.                         'del' newName
  316.                     else if (resp = "B") then
  317.                         call backupFile newName
  318.                     else
  319.                         moveOK = 0
  320.                 end
  321.             end
  322.             else
  323.                 if (interactive) then
  324.                     moveOK = (queryYN(interactMsg))
  325.  
  326.             /* finally, move file */
  327.             if (moveOK) then
  328.                 if (\test) then do
  329.                     'copy' oldname newname ">NUL"
  330.                     'if exist' newname 'del' oldname '/N'
  331.                 end
  332.                 else if debug then do
  333.                     Say '    -- copy' oldname newname
  334.                     Say '    -- del' oldname
  335.                 end
  336.         end
  337.  
  338.         when renMode then do
  339.         /* rename only */
  340.             newNameOnly = getNewName(files.i)
  341.  
  342.             if (FAT) then
  343.                 newNameOnly = makeFAT(newNameOnly)
  344.  
  345.             call renameFile oldname newNameOnly
  346.         end
  347.  
  348.         when (tolower) | (toupper) then do
  349.         /* rename to lower or upper case */
  350.             if (tolower) then
  351.                 newNameOnly = lowercase(oldNameOnly)
  352.             else
  353.                 newNameOnly = translate(oldNameOnly)
  354.  
  355.             if (FAT) then
  356.                 newNameOnly = makeFAT(oldNameOnly)
  357.  
  358.             call renameFile oldname newNameOnly
  359.         end
  360.  
  361.         when (FAT) then do
  362.         /* rename to FAT format (8+3) */
  363.             newNameOnly = makeFAT(oldNameOnly)
  364.  
  365.             call renameFile oldname newNameOnly
  366.         end
  367.  
  368.         when (realtolong) then do
  369.         /* change name to .LONGNAME */
  370.             if (longname_ \= "") & (longname \= oldNameOnly) & (pos('"',longname) = 0) then do
  371.                 newnameOnly = longname
  372.                 if (FAT) then newNameOnly = makeFAT(oldNameOnly)
  373.  
  374.                 /* now replace invalid characters that may be in .LONGNAME */
  375.                 if invalidName(longname) then
  376.                     do i2 = 1 to length(invalidChars)
  377.                         newNameOnly = translate(newNameOnly, '!', substr(invalidChars, i2, 1))
  378.                     end
  379.  
  380.                 call renameFile oldname newNameOnly
  381.              end
  382.         end
  383.         otherwise ;
  384.     end /* select */
  385. end /* do files.i */
  386.  
  387. if (test) then say dontWorryMsg
  388.  
  389. exit
  390.  
  391. getNewName:
  392.     _oldname = arg(1)
  393.     if (wildcards) then
  394.         _newname = strReplace(filespec('name', _oldname), old.wild.sub, new.wild.sub)
  395.     else
  396.         _newname = new.spec
  397. return _newName
  398.  
  399. makeFAT: procedure expose debug
  400.     _old = arg(1)
  401.     _p = pos(".", _old)
  402.     _p2 = _p
  403.     if _p2 > 8 then _p2=8
  404.     if (_p > 0) then do
  405.         _new = left(_old, _p2-1)||"."||substr(_old, _p+1, 3)
  406.     end
  407.     else _new = left(_old, 8)
  408.     if debug then
  409.         say "    makeFAT:" _old "-->" _new
  410. return _new
  411.  
  412. deleteLongname:
  413.     realname = arg(1)
  414.     rc = SysGetEA(realname, ".LONGNAME", "longname_")
  415.     longname = substr(longname_, 5)
  416.  
  417.     if (longname \= "") then
  418.         if ((\invalidName(longname)) | force) then do
  419.             if \test then
  420.                 call SysPutEA realname, ".LONGNAME", ""
  421.  
  422.             if (\quiet) then do
  423.                 rc = SysGetEA(realname, ".LONGNAME", "longname2")
  424.                 if ((longname2 \= "") & \test & \quiet) then
  425.                     Say strReplace(inuseMsg, '%a', realname)
  426.                 else
  427.                     if (\quiet) then
  428.                         Say strReplace(strReplace(longDelMsg, '%b', longname), '%a', realname)
  429.             end
  430.         end
  431.         else
  432.             if \quiet then
  433.                 Say skipMsg
  434. return
  435.  
  436. renameFile:
  437.     if (deleteLong) then
  438.         call deleteLongname oldname
  439.  
  440.     if (filespec("NAME", oldname) \= newNameOnly) then do
  441.         if (verbose | interactive) then
  442.             say strReplace(strReplace(renameMsg, '%a', oldname), '%b', newNameOnly)
  443.         else if (\quiet) then say oldname
  444.  
  445.         renOK = \interactive
  446.         if (interactive) then
  447.             renOK = queryYN(interactMsg)
  448.  
  449.         if (renOK) then
  450.             if (\test) then
  451.                 'ren' oldname newNameOnly
  452.             else if debug then
  453.                 Say '    -- ren' oldname newNameOnly
  454.     end
  455. return
  456.  
  457. backupFile:
  458.     oldfile = arg(1)
  459.     oldfile2 = oldfile
  460.     ext = ""
  461.     p = lastpos(".", oldfile)
  462.     if (p > 0) then do
  463.         ext = substr(oldfile, p)
  464.         oldfile2 = left(oldfile, p-1)
  465.     end
  466.     p = lastpos("!", oldfile2)
  467.     if (p > 0) then do
  468.         if datatype(substr(oldfile2, p+1)) = "NUM" then do
  469.             bak = substr(oldfile2, p+1)+1
  470.             oldfile2 = left(oldfile2, p-1)
  471.         end
  472.         else bak = 1
  473.     end
  474.     else bak = 1
  475.  
  476.     newfile = filespec('name', oldfile2)
  477.     if (FAT) then newfile = left(newfile, 8-length(bak)-1)
  478.     do while (stream(moveTo||newfile"!"bak||ext,'c','query exist') \= "")
  479.         bak = bak+1
  480.         if (FAT) then newfile = left(newfile, 8-length(bak)-1)
  481.     end
  482.  
  483.     if (verbose) then say strReplace(strReplace(backedupMsg, '%b', newfile"!"bak||ext), '%a', oldfile)
  484.     'ren' oldfile newfile"!"bak||ext
  485. return
  486.  
  487.  
  488. strReplace:
  489.     parse arg str, old, new
  490.     p = pos(translate(old), translate(str))
  491.     if (p > 0) then
  492.         return left(str, p-1)||new||substr(str,p+length(old))
  493.     else
  494.         return str
  495.  
  496. invwc:
  497.     'call xhelp "'invwcMsg'"'
  498.     exit
  499.  
  500. lowercase:
  501.     return translate(arg(1), 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')
  502.  
  503. invalidName:
  504.     invalid = 0
  505.     do i9 = 1 to length(longname)
  506.         if (pos(substr(longname, i9, 1), invalidChars) \= 0) then
  507.             invalid = 1
  508.         if invalid then leave
  509.     end
  510. return invalid
  511.  
  512. queryYN:
  513.     if \alwaysReplace then do
  514.         call charout , arg(1)
  515.         key = ''
  516.         do until pos(key,"YNA") > 0
  517.            key = translate(SysGetKey("NOECHO"))
  518.         end /* do */
  519.         Say key
  520.         if (key = "A") then
  521.             alwaysReplace = 1
  522.      end
  523.      if (alwaysReplace) then key = "Y"
  524. return (translate(key) = "Y")
  525.  
  526. queryExists:
  527.     if \alwaysReplace then do
  528.         call charout , arg(1)
  529.         key = ''
  530.         do until pos(key,"RBSA") > 0
  531.            key = translate(SysGetKey("NOECHO"))
  532.         end /* do */
  533.         Say key
  534.         if (key = "A") then
  535.             alwaysReplace = 1
  536.      end
  537.      if (alwaysReplace) then key = "R"
  538. return key
  539.  
  540. halt:
  541.   "call xhelp -f abortMsg xren"
  542.   exit
  543.  
  544.  
  545.  
  546.  
  547.  
  548.  
  549.  
  550.  
  551.  
  552.  
  553.  
  554.  
  555.  
  556.  
  557.  
  558.  
  559.