Last active
August 29, 2015 14:02
-
-
Save mgrandi/e784f2365ac922b0e248 to your computer and use it in GitHub Desktop.
ratchet_and_clank_nexus_rename_soundfiles.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# | |
# script to name audio files from 'ratchet and clank into the nexus' to human readable names | |
# | |
# aka resident_sound.dat -> cha_clank_voc_tossspecialb_mdc.dat | |
# | |
# Jun 23, 2014 Mark Grandi | |
# | |
import argparse, sys, re, os.path, os, shutil | |
def _readCString(theFile): | |
''' method that will read a c string given a file and return it''' | |
# need to read bytes until we get null byte cause this is a null | |
# terminated c string | |
stringBuffer = bytearray() | |
while True: | |
tmp = theFile.read(1) | |
if tmp is not None and len(tmp) != 0: | |
if tmp != b'\x00': | |
stringBuffer += tmp | |
else: | |
# found the null terminator, we are done | |
return stringBuffer.decode("utf-8") | |
else: | |
# end of file? | |
# print("unexpected end of file.... trying to convert what we have" + | |
# " to utf-8\n") | |
return stringBuffer.decode("utf-8") | |
def renameFiles(args): | |
'''renames ratchet and clank sound files to have a human readable name | |
@param args - the namespace object we get from argparse.parse_args() | |
''' | |
if args.verbose: | |
print("Regex is: '{}'".format(args.fileToRenameRegex)) | |
print("Searching directory: '{}'".format(args.inputFolder)) | |
# dirpath is a string, the path to the directory. | |
# dirnames is a list of the names of the subdirectories in dirpath (excluding '.' and '..'). | |
# filenames is a list of the names of the non-directory files in dirpath. | |
for dirpath, dirnames, filenames in os.walk(args.inputFolder): | |
for iterFile in filenames: | |
curPath = os.path.join(dirpath, iterFile) | |
if args.fileToRenameRegex.search(iterFile) != None: | |
if args.verbose: | |
print("file {} matched, renaming".format(curPath)) | |
name = None | |
with open(curPath, "rb") as f: | |
# see if it matches the file we expect | |
header = f.read(4) | |
if header != "IGHW".encode("utf-8"): | |
print("\tFile {} matched regex but its header did not match what we expect! got {} but expected 'IGHW'".format(curPath, header)) | |
continue | |
# go to byte 256 and read a C string | |
f.seek(256) | |
name = _readCString(f) | |
# now rename it to be the name we got from the file + file extension | |
outputFile = os.path.join(args.outputFolder, name + os.path.splitext(curPath)[1]) | |
shutil.copyfile(curPath, outputFile) | |
print("{} renamed to {}".format(curPath, outputFile)) | |
else: | |
if args.verbose: | |
print("file {} did not match regex, skipping".format(curPath)) | |
print("done!") | |
def isDirectoryType(stringArg): | |
''' helper method for argparse to see if the argument is a directory | |
@param stringArg - the argument we get from argparse | |
@return the path if it is indeed a directory, or raises ArgumentTypeError if its not.''' | |
path = os.path.realpath(os.path.normpath(stringArg)) | |
if not os.path.isdir(path): | |
raise argparse.ArgumentTypeError("{} is not a directory!".format(path)) | |
return path | |
def isRegexType(stringArg): | |
''' helper method for argparse to see if the argument is a valid regex expression | |
@param stringArg - the argument we get from argparse | |
@return the compiled RE object if it is indeed a directory, or raises ArgumentTypeError if its not.''' | |
compiledRe = None | |
try: | |
compiledRe = re.compile(stringArg) | |
except re.error as e: | |
# not a valid regex expression | |
raise ArgumentTypeError("{} is not a valid regular expression! error: {}".format(stringArg, e)) | |
return compiledRe | |
if __name__ == "__main__": | |
# if we are being run as a real program | |
parser = argparse.ArgumentParser(description="script to name audio files from 'ratchet and clank into the nexus' to human readable names", | |
epilog="Copyright Jun 23, 2014 Mark Grandi") | |
# optional arguments, if specified these are the input and output files, if not specified, it uses stdin and stdout | |
parser.add_argument('inputFolder', type=isDirectoryType, help="the folder that contains the files to rename") | |
parser.add_argument("outputFolder", type=isDirectoryType, help="Where to output the resulting files") | |
parser.add_argument('fileToRenameRegex', type=isRegexType, help="the regex to use to figure out what files to rename, " | |
"if unsure just type the entire name (like 'resident_sound.dat')") | |
parser.add_argument("--verbose", action="store_true", help="use this to increase verbosity") | |
renameFiles(parser.parse_args()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment