Sunday 17 July 2016

Windows Batch Rename

There are numerous window tools out there that allows you to manage batch window files in the way that Linux does, and I didn't have to write this but I did anyway, for practice.

The main thing I learnt with this project is just how seemingly simple tasks can be difficult for the computer to implement, and by which I mean counting in this specific case.

It's not something you'd see often nowadays, but when you have long sequences of files numbered 1 - 100 for example, the computer is not going to number them 1 - 100 for you. It will be 1, 10, 11....19, 2, 20, 21.....and so on.

Given that in animation, numbering of the files are super important, if the batch renamer can't sort the files into a list naturally, then it's worse than useless. It would rename the number 10 frame as 2, and the number 2 frame as 10....So natural sorting turns out to be pretty tricky to implement. My original code just for natural sorting was about 40 lines or so and wonky, but I found an implementation using regular expression that was much simpler. Unfortunately, I could no longer remember where I found the code from so could not attribute it. In any case, the code comes below, runs off IDLE, and has no UI hahaha. The key portion for natural sorting is in the first 3 functions.

----------------------------
import os, string
from os import path, listdir, rename
from string import Template, zfill
usrInput=raw_input("Enter directory pathway: ")
workDir=usrInput.replace("\\", "\\\\")
fLst=os.listdir(workDir)

def tryint(s):
    try:
        return int(s)
    except:
        return s
       
def numeric_key(s):
    import re
    return [tryint(c) for c in re.split("([0-9]+)", s)]

def natsort(Lst):
    fLst.sort(key=numeric_key)
   
natsort(fLst)
print fLst

def srep():
    nWord = raw_input("enter new name: ")
    old = raw_input("enter old name: ")
    if len(old)<1:
        print "no entry detected, try again"
        exit()
    for item in fLst:
        original_file=os.path.join(workDir, item)
        if old in original_file:
            base, ext = os.path.splitext(original_file)
            newFile=item.replace(old, nWord)
            os.rename(original_file, (os.path.join(workDir, newFile)))
            print '{0} --> {1}'.format(item, newFile)

       
def rname():
    count = 0
    class BatchRename(Template):
        delimiter = '%'
    usrInpFmt=raw_input('Enter rename style (%d-date %n-seqnum %f-format):  ')
    pad=int(raw_input('Enter padding: '))
    start=int(raw_input('Start From?: '))
    fmt=usrInpFmt+"%n%f"
 
    t = BatchRename(fmt)

    for i, filename in enumerate(fLst):
        original_file=os.path.join(workDir, filename)
        count=start+i
        base, ext = os.path.splitext(filename)
        newName = t.substitute(n=string.zfill(count, pad), f=ext)
        os.rename(original_file, (os.path.join(workDir, newName)))
        print '{0} --> {1}'.format(filename, newName)

style=raw_input("function type? 1) search and replace 2) rename _ ")
if style is "1":
    srep()
elif style is "2":
    rname()
else:
    print "function not within call"
----------------------------

No comments:

Post a Comment