Article 151034 of comp.os.vms:
Hi,

After my signature there is a new version of my utility "fix_unixname.com".
It is basically a tool for massive renamings of the sort that are 
painful to do using simple wildcards, that is, substitutions within and
between the filename and extension parts of a filename.

These are the sorts of renames it can perform, all on a wildcarded filename
specification. 

  $RC_100A.T7$5NS$EQ       -> RC_100A_T7.SEQ  (remove Unix escape characters
                                               watch out for decw$ sys$ and 
                                               so forth!)
  $RC_100A.T7$5NS$EQ$5NTXT -> RC_100A_T7.SEQ  (ditto, also do subsitutions,
                                               here "seq.txt -> .seq")
  FOO.PICT_TAR_Z           -> FOO_PICT_TAR.Z  (move around _ vs .)
  VAX_04_1995.DAT          -> VAX_1995_04.DAT (swap around arbitrary pieces
                                               of file names, here anything
                                               in the 04 position would 
                                               swap with the 1995 position )

Getting the syntax right for some renames can take a bit of trial and
error, so there is now also a debug/trace option.  This shows what's going
on in the substitute and swap phases, but doesn't actually do any renaming.

Ok, so you don't need this often, but next time you have to do thousands
of the above sorts of renames, keep it in mind.

Regards,

David Mathog
mathog@seqaxp.bio.caltech.edu
Manager, sequence analysis facility, biology division, Caltech 
**********************************************************************
$!FIX_UNIXNAME.COM
$! 7-DEC-1995, David Mathog, Biology Division, Caltech
$!
$! This routine converts hideous Unixy filenames, such as:
$!     $RC_100A.T7$5NS$EQ$5NTXT
$! to a more civilized form, such as:
$!     rc_100a_t7.seq
$!
$! Parameters are:
$! P1  Name of file or wildcarded search string
$! P2  "Period priority".  Options are FIRST and LAST, default being
$!     LAST.  These take effect after the string is converted to the
$!     unix form, ie RC_100A.T7.Seq.txt
$! P3  Replacement pairs.  Not case sensitive.  A string like:
$!     "seq.txt,.txt,.bin,.abi"  These consist of a pattern to find,
$!     and a string to replace it with.  Most useful for removing the
$!     drivel that Mac's FETCH sticks on the end. "^" matches begin and
$!     end of a filename, ie ".bin^" will only pick up a final ".bin"
$! P4  Anything but a "" silences logging of changes
$! P5  Reorder target pairs.  For instance, 
$!      foo_1996_01.dat -> foo_01_1996.dat, use:
$!     "foo_,1,,4,_,3,,2,.dat,5"
$!     Which works this way, it finds 4 pieces:
$!             1:  foo_   (found)        -> 1     foo_
$!             2:  1996   (inferred)     -> 4     01
$!             3:  _      (found)        -> 3     _
$!             4:  01     (inferred)     -> 2     1996
$!             5:  .dat   (found)        -> 5     .dat
$!
$! P6  If set, enter debugging/trace mode.  File names will
$!     not be affected.
$!
$! In first pass all $5N are converted to "."
$! In second pass all single $ are removed.
$! In third pass all replacements are done
$! In fourth pass all reorders are done
$! In fifth pass, reduce to one "."
$!
$! Here is an example use, which cleans up ABI sequence files transferred 
$! with the Mac program fetch.  All ".seq.txt" files become ".seq", and 
$! all ".bin" files become ".abi"
$!
$!  $ @fix_unixname disk:[directory.subdirectory...]*.*  "" ".seq.txt,.seq,.bin^,.abi^"
$!
$! Here is an example to convert "foobar_tar.;1" to "foobar.tar" (these 
$! often result after running gunzip on a Unix produced file.)  It replaces
$! all _ with ".", then deletes the final ".".
$!
$!  $ @fix_unixname *.* "" "_,.,.^,^"
$!
$! Here is an example that converts like this:
$!     VAX_01_1996.DAT -> VAX_1996_01.DAT
$!
$! $  @fix_unixname vax_*_19*.dat "" "" "" "VAX_,1,,4,_,3,,2,.dat^,5"
$!
$! Note that especially for the swapping around mode it is crucial
$! that the search string in P1 not pick up the already swapped (ie,new)
$! filename.  If it does, it will swap it, then swap it back!!!
$!
$!
$! Revisions
$! 12-JUL-1996, David Mathog, Biology Division, Caltech
$!  Added swap stuff to change the order of the pieces in names.
$!  Added a trap at the bottom so that nonwildcarded P1 don't loop
$!    forever.
$!  Added debugging/trace mode
$!
$ if(P1 .nes. "")
$ then
$   searchfor = P1
$ else
$   inquire searchfor "Enter a Unixy filename or wildcarded search string"
$ endif
$!
$ if(P2 .nes. "")
$ then
$   PerPri = F$EDIT(P2,"TRIM,UPCASE")
$   if(PerPri .nes. "FIRST")then PerPri = "LAST"
$ else
$   PerPri = "LAST"
$ endif
$!
$ reppairs=""
$ if(P3 .nes. "")then reppairs = P3
$ reppairs = f$edit(reppairs,"UPCASE,TRIM")
$!
$ silent = P4
$!
$ swappairs=""
$ if(P5 .nes. "")then swappairs = P5
$ swappairs = f$edit(swappairs,"UPCASE,TRIM")
$!
$ trace = P6
$!
$!  Top of search string
$!
$TOP:
$  file = f$search(searchfor)
$  if(file .eqs. "")then exit
$  target   = f$parse(file,,,"NAME") + f$parse(file,,,"TYPE")
$  yuckname = "^" + target + "^"
$!
$! pass1, convert all $5N to "."
$!
$TOP1:
$  site = f$locate("$5N",yuckname)
$  len  = f$length(yuckname)
$  if(site .ne. len)
$    then
$       yuckname=   f$extract(0,site,yuckname) -
                  + "." -
                  + f$extract(site+3,len-site-3,yuckname)
$       goto top1
$    endif  
$!
$! pass2, get rid of all loose "$"
$!
$TOP2:
$  back  = f$element(1,"$",yuckname)
$  if(back .nes. "$")
$  then
$       yuckname = yuckname - "$"
$       goto top2
$  endif
$!
$! pass3, Do all substitutions
$!
$ if(reppairs .eqs. "")then goto bottom3
$ if(trace .nes. "")then write sys$output "Replacing pieces"
$count = 0
$TOP3:
$  was    = f$element(count,",",reppairs)
$  willbe = f$element(count+1,",",reppairs)
$  count  = count + 2
$  if(was .eqs. "," .or. willbe .eqs.",")then goto bottom3
$  site   = f$locate(was,yuckname)
$  len    = f$length(yuckname)
$  lenw   = f$length(was)
$  if(site .ne. len)
$  then
$  if(trace .nes. "")then write sys$output "before = ",yuckname
$       yuckname=   f$extract(0,site,yuckname) -
                  + willbe -
                  + f$extract(site+lenw,len-site-lenw,yuckname)
$  if(trace .nes. "")then write sys$output "after = ",yuckname
$  endif  
$  goto top3
$bottom3:
$!
$! pass4, Do all swaps.  First it finds all pieces sequentially
$!  and bails on any that are missing a piece.  Then it rearranges
$!  them.
$!
$ if(swappairs .eqs. "")then goto bottom4
$ if(trace .nes. "")then write sys$output "Swapping pieces"
$ count = 0
$ outcount = 0
$ scan = 0
$ chewme = yuckname
$TOP4:
$  if(trace .nes. "")then write sys$output "chewme ",chewme
$  was    = f$element(count,",",swappairs)
$  willbe = f$element(count+1,",",swappairs)
$  if(trace .nes. "")then write sys$output "what,where ",was," ",willbe
$  count  = count + 2
$  if(was .eqs. "," .or. willbe .eqs.",")
$  then
$     outcount = outcount + 1
$     sw_'outcount'_string=""
$     if(trace .nes. "")then write sys$output "sw_''outcount'_string ",sw_'outcount'_string
$     goto nearbottom4
$  endif
$  if(was .eqs. "")
$  then
$    if(scan .eq. 1)
$    then
$      write sys$output "Fatal syntax error in swap string = ''swappairs'"
$      exit      
$    endif
$    scan = willbe
$    goto top4
$  endif
$  site   = f$locate(was,chewme)
$  len    = f$length(chewme)
$  lenw   = f$length(was)
$!
$! an element was not found, so no swaps
$!
$  if(site .eq. len)then goto bottom4
$!
$! pick up the implied piece, if called for
$!
$  if(scan .ne. 0)
$  then
$     sw_'scan'_string =   f$extract(0,site,chewme)
$     if(trace .nes. "")then write sys$output "sw_''scan'_string ",sw_'scan'_string
$     outcount = outcount + 1
$     scan = 0
$  endif
$  outcount = outcount + 1
$  sw_'willbe'_string =   f$extract(site,lenw,chewme)
$  if(trace .nes. "")then write sys$output "sw_''willbe'_string ",sw_'willbe'_string
$  chewme = f$extract(site+lenw,len-site-lenw,chewme)
$  goto top4
$!
$! here finish up by rearranging the pieces
$!
$nearbottom4:
$  count = 1
$  yuckname = ""
$nb4:
$  if(sw_'count'_string .nes. "")
$  then
$     yuckname = yuckname + sw_'count'_string
$     count = count + 1
$     goto nb4
$  endif
$bottom4:
$!
$!  Pass5, reduce to one period, all others become "_".
$!
$ onedot = -1
$ len  = f$length(yuckname)
$ top5:
$ site = f$locate(".",yuckname)
$ if(site .ne. len)
$ then
$    yuckname=   f$extract(0,site,yuckname) -
                 + "_" -
                 + f$extract(site+1,len-site-1,yuckname)
$    if(PerPri .eqs. "FIRST")
$    then
$       if(onedot .eq. -1)then onedot = site
$    else
$       onedot = site
$    endif
$    goto top5
$ endif  
$!
$!
$!
$    yuckname=   f$extract(0,onedot,yuckname) -
                 + "." -
                 + f$extract(onedot+1,len-onedot-1,yuckname)
$!
$! strip off the beginning and ending "^" and put the directory stuff back on
$!
$ yuckname = yuckname - "^" - "^"
$ if(target .nes. yuckname)
$ then
$   if(silent .eqs. "")
$   then
$     write sys$output "was: ''target'"
$     write sys$output "is:  ''yuckname'"
$   endif
$ if(trace .eqs. "")
$ then
$    rename 'file' 'yuckname'
$ endif
$!
$!  trap searchfor without wildcard - this could loop endlessly
$!  for some commands
$!
$ len  =  f$length(searchfor)
$ site1 = f$locate("*",searchfor)
$ site2 = f$locate("%",searchfor)
$ if(len .eq. site1 .and. len .eq. site2)then exit
$ goto top


