#!/usr/bin/python import sys,string,os,glob # ******************************************************************* # *************** lseq V 2.20 - Andrew Whitehurst ******************* # ************************* 16 April 2010 *************************** # ******************************************************************* # lseq IS A UTILITY THAT SCANS A DIRECTORY AND RETURNS FORMATTED LISTS OF # SEQUENCES OF FRAMES MAKING IT EASIER TO SEE WHICH FRAMES ARE MISSING # WHAT THE FRAME RANGES ARE AND SO ON. IT RETURNS THE LIST IN A "SHAKE-STYLE" # FORMATTING # 2.20 FIXES A BUG WHEN SEQUENCES CROSS FROM TENS TO HUNDREDS, HUNDREDS TO THOUSANDS ETC. FROM BEING LISTED AS TWO SEQUENCES # 2.10 NOW ADDS A FLAG TO HANDLE DIFFERENT NEGATIVE FRAME NUMBER PADDING SCHEMES # DEFINE ALL THE FUNCTIONS FOR THINGS WE'RE GOING TO NEED THE UTILITY TO DO # ************ FUNCTIONS BEGIN HERE ************** # BUILD A STRING OF FRAME NUMBERS FROM A SUPPLIED LIST def makeFrameList(inputList,pad): outputString = "" if len(inputList) > 1: lastTestedNumber = inputList[0] minRun = lastTestedNumber # <- minRun WILL BE USED TO NOTE THE LOW NUMBER IN A RUN OF CONSECUTIVE FRAMES del inputList[0] # <- WE KNOW THAT WE WILL ALWAYS WANT TO PRINT THE FIRST NUMBER IN THE SEQUENCE AND AS IT'S STORED IN lastNumberTested WE CAN DELETE IT NOW SO IT DOESN'T GET COUNTED TWICE inputList.append(inputList[(len(inputList)-1)]+10) # <- I APPEND A VALUE TO THE LIST AS THE LOOP WILL OTHERWISE MISS OFF THE LAST CORRECT VALUE maxRun = minRun # <- maxRun WILL MARK THE HIGH VALUE IN A CONSECUTIVE RUN OF FRAMES for x in inputList: # <- WORK OUR WAY THROUGH THE LIST OF FRAME NUMBERS if x == (lastTestedNumber + 1): # <- TEST FOR A CONSECUTIVE FRAME maxRun = x lastTestedNumber = x elif x != (lastTestedNumber + 1): # <- THE FRAMES AREN'T CONSECUTIVE, TIME TO DECIDE WHAT TO DO if maxRun == minRun: # <- LOOKS LIKE A SINGLE FRAME ALL ON ITS OWN if maxRun < 0: outputString += string.zfill(maxRun,(pad + 1)) + ","# <-- JUST ADD ONE VALUE WITH CORRECT PADDING FOR NEGATIVE NUMBERS else: outputString += string.zfill(maxRun,pad) + ","# <-- JUST ADD ONE VALUE minRun = x maxRun = x elif maxRun != minRun and minRun < maxRun: # <- CHECK FOR A LEGITIMATE RUN OF FRAMES outputString += (str(minRun) + "-" + str(maxRun) + ",") # <-- ADD A RUN OF VALUES minRun = x maxRun = x lastTestedNumber = x outputString = outputString[:-1] # <-- TAKE THE TRAILING COMMA OFF THE END OF THE SEQUENCE elif len(inputList) == 1: # <- IF THE SEQUENCE IS ONLY ONE FRAME THEN JUST OUTPUT IT CHECKING FOR PADDING OF NEGATIVE NUMBERS if inputList[0] < 0: outputString = string.zfill(inputList[0],(pad + negPad)) else: outputString = string.zfill(inputList[0],pad) return outputString # WHAT TO WRITE IF SOMETHING GOES WRONG def errorMessage(): print "\n\tUSAGE : lseq [OPTION] [DIRECTORY]\n" print "\tlseq will list numbered sequences in an easy to ready format" print "\tthat will show ranges of existing files. This enables the user" print "\tto easily see where files are missing and to see multiple image" print "\tsequences contained within the same directory. The list is" print "\tin a \"Shake-style\" format, i.e. file.1-7,0010,0015,18-20#.ext\n" print "\tlseq will default to treating negative frames like abc.-001.ext as" print "\ta four frame padded number. If you wish to treat such a frame as " print "\tthree frame padding add the -oldPad flag option.\n" print "\tAn optional valid directory path may be specified to run the" print "\tthe command on.\n\n" sys.exit(1) # STRING TO INT FUNCTION def stringToInt(inputString): tweakVal = inputString outVal = 0 if inputString[:1] == "-": # <- TAKE CARE OF NEGATIVE VALUES multVal = -1 tweakVal = inputString[1:] else: multVal = 1 if tweakVal.isdigit() != 1: print(str(tweakVal) + " is a non-numeric frame value.") else: outVal = int(tweakVal)*multVal return outVal # WORK OUT THE FILENAME STEM def getFileName(inputString): outString = " " noExt = inputString.rsplit(".",1) # <- CHOP OFF THE FILE EXTENSION for i in range(len(noExt[0])): if inputString[(len(noExt[0])-i)].isdigit() == 1 and inputString[(len(noExt[0])-(i+1))].isdigit() == 0: # <- FIND WHERE THE NUMBERS STOP GOING RIGHT TO LEFT ALONG THE FILENAME AND FRAME NUMBER outString = inputString[0:len(noExt[0])-i] break # <- STOP WHEN WE FIND THE END OF THE FRAME NUMBER DIGITS if outString[-1:] == "-": outString = outString[:-1] # <- REMOVE THE MINUS SIGN FROM NEGAIVE FRAME NUMBERS return outString # CALCULATE FRAME NUMBERS def getFrameNumber(inputString): outString = "NG" noExt = inputString.rsplit(".",1) for i in range(len(noExt[0])): if noExt[0][(len(noExt[0])-1-i)].isdigit() == 0 and noExt[0][(len(noExt[0])-1-i)] != "-": # <- WORK RIGHT TO LEFT THROUGH THE STRING TAKING THE NEGATIVE FRAM NUMBER POSSIBILITY INTO ACCOUNT outString = noExt[0][len(noExt[0])-i:len(noExt[0])] break return outString # WORK OUT THE FILE'S EXTENSION def getExtension(inputString): outString = "" ext = inputString.rsplit(".",1) outString = "."+ext[1] return outString # FUNCTION TO RETURN FRAME-PADDING LENGTH - USES THE PREVIOUSLY DEFINED negPad VALUE TO DETERMINE WHTHER WE # REGARD -#### TO BE 5 FRAME OR 4 FRAME PADDED def getFramePadding(inputFrame): outPad = 0 if len(inputFrame) > 1 and inputFrame[0:] == "-" and inputFrame[1:] == "0": outPad = len(inputFrame)- negPad if len(inputFrame) > 1 and inputFrame[0:] == "0": outPad = len(inputFrame) return outPad # ******** END OF FUNCTIONS ********* # negPad IS TO HANDLE WHETHER WE REGARD -#### AS FOUR OR FIVE FRAME PADDING negPad = 0 # MAIN BODY OF CODE STARTS HERE # DO THE ERROR CHECK THING ON USER INPUT if len(sys.argv) > 3: errorMessage() if len(sys.argv) >= 2: if sys.argv[1] == "-h" or sys.argv[1] == "-help" or sys.argv[1] == "-H" or sys.argv[1] == "--help": errorMessage() if sys.argv[1] == "-oldPad": negPad = 1 # BUILD THE PATH THAT IS TO BE TESTED, WILL USE THE CWD IF NO DIRECTORY IS SUPPLIED testPath = "" if len(sys.argv) >= 2 and sys.argv[1] != "-oldPad": if os.path.exists(sys.argv[len(sys.argv)-1]): testPath = sys.argv[len(sys.argv)-1] else: errorMessage() # BUILD A LIST OF ALL THE RELEVENT FILES fileList = glob.glob(testPath+"*.*") # ERROR CHECK FOR THE EXISTENCE OF SOME VALID FILES if len(fileList) < 1: print "\n\tNo valid files found.\n" sys.exit(1) # DEFINE OUR ARRAYS FOR STORING DATA fileName = [] framePad = [] extension = [] frameNum = [] for x in fileList: # <- BUILD THE LISTS OF ALL THE CHOPPED UP FILE INFO. if getFrameNumber(x) != "": # <- FILTER OUT NON-FRAME TYPE FILES fileName.append(getFileName(x)) frameNum.append(getFrameNumber(x)) framePad.append(getFramePadding(getFrameNumber(x))) extension.append(getExtension(x)) uniqueFileName = [] uniqueFramePad = [] uniqueExtension = [] patternExists = 0 # WORK OUT WHICH COMBINATIONS OF FILENAME, FRAME-PADDING AND EXTENSION ARE UNIQUE if len(fileName) == len(frameNum) and len(fileName) == len(extension): for i in range(len(fileName)): for x in range(len(uniqueFileName)): if fileName[i] == uniqueFileName[x] and framePad[i] == uniqueFramePad[x] and extension[i] == uniqueExtension[x]: patternExists = 1 if patternExists != 1: uniqueFileName.append(fileName[i]) uniqueFramePad.append(framePad[i]) uniqueExtension.append(extension[i]) else: patternExists = 0 else: errorMessage() outputString = "\n" # <- THE OUTPUT STRING TO BE PRINTED TO THE SHELL tempFrameList = [] for i in range(len(uniqueFileName)): # <- FOR EVERY UNIQUE FILENAME,PAD,EXTENSION COMBO... for x in range(len(fileName)): # <- FOR EVERY FILE IN OUR ORIGINAL FULL-LENGTH LIST... if fileName[x] == uniqueFileName[i] and framePad[x] == uniqueFramePad[i] and extension[x] == uniqueExtension[i]: # <- IF IT MATCHES THE TEST CONDITION if frameNum[x] != "": tempFrameList.append(stringToInt(frameNum[x])) # <- ADD THE FRAME TO THE LIST OF FRAMES FOR THIS FILENAME,PAD,EXT COMBO tempFrameList.sort() if len(tempFrameList) > 1: # <- FOR LISTS LEN >1 BUILD A STRING AND ADD IT TO THE OUTPUT STRING outputString += "\t" + str(uniqueFileName[i] + makeFrameList(tempFrameList,uniqueFramePad[i]) + "#" + uniqueExtension[i] + "\n") elif len(tempFrameList) == 1: # <- FOR LISTS LEN == 1 BUILD A STRING AND ADD IT TO THE OUTPUT STRING outputString += "\t" + str(uniqueFileName[i] + makeFrameList(tempFrameList,uniqueFramePad[i]) + uniqueExtension[i] + "\n") tempFrameList[:] = [] # <- CLEAR THE LIST OF FRAMES READY FOR THE NEXT PASS print outputString # <- THIS IS THE FINAL OUTPUT TO THE SHELL