Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/env python
- ################################################################################
- # Program: steel_reserve.py
- # Version: 0.8
- # Original Author: James Hendrie <hendrie dot james at gmail dot com>
- # Contributors:
- # License: GPL 3 (http://www.gnu.org/licenses/gpl.html)
- # Last edit: 2012-08-23
- # Description: A thing I made for spoony. First it renames all the
- # files in the current directory to be properly 'unixy',
- # then it creates an xml file for each one.
- ################################################################################
- import sys, os
- import shutil
- ## 'constants'
- SELF_NAME = sys.argv[0] ## Just for the sake of clarity
- ## A tuple of things that will be removed from any filename strings
- VERBOTEN = ('!',',',':','+','=','&')
- LESS_VERBOTEN = ('(',')', ';')
- ## A tuple of file formats that will be renamed. Everything else is ignored.
- ## Do include the period. Don't worry about capitalization.
- VALID = ('.mp4','.webm','.flv','.mkv','.m4v')
- ## When entering tags, convert spaces to commas
- ## If false, they're converted to underscores instead
- SPACES_TO_COMMAS = True
- ## Use underscores instead of spaces in tags. If false, the tag will be
- ## enclosed in quotation marks. I don't know if that's 'legal' or not, though.
- USE_UNDERSCORES = True
- ## The file activation date
- ACTIVATION_DATE = "2012-09-01"
- REPORT = "[email protected]"
- ## The extension for the xml file
- XML_EXTENSION = '.xml'
- ## Redundant, but I'll keep it here just in case.
- XML_TEMPLATE = """
- <?xml version="1.0" encoding="UTF-8"?>
- <file_upload>
- <report>[email protected]</report>
- <item>
- <filename>ENTER_VIDEO_FILENAME.flv</filename>
- <filesize>2901436</filesize>
- <title>
- <![CDATA[ENTER TITLE HERE]]>
- </title>
- <duration>21</duration>
- <tags>tag1,tag2,tag3</tags>
- <age>0</age>
- <description>
- <![CDATA[ENTER DESCRIPTION HERE]]>
- </description>
- <activation_date>2012-09-01</activation_date>
- </item>
- <item>
- <filename>ENTER_VIDEO_FILENAME.mp4</filename>
- <filesize>3112933</filesize>
- <title>
- <![CDATA[ENTER TITLE HERE]]>
- </title>
- <duration>44</duration>
- <tags>tag1,tag2,tag3</tags>
- <age>0</age>
- <description>
- <![CDATA[ENTER DESCRIPTION HERE]]>
- </description>
- <activation_date>2012-09-01</activation_date>
- </item>
- </file_upload>
- """
- def get_input(queryString):
- '''
- This exists for compatibility reasons (python 2 vs python 3)
- '''
- if sys.version[0] == '2':
- theInput = raw_input(queryString)
- elif sys.version[0] == '3':
- theInput = input(queryString)
- return theInput
- def set_options():
- '''
- Set the default options for the program.
- '''
- ## Defaults
- options = {}
- options['autogen'] = False
- options['activationDate'] = ACTIVATION_DATE
- options['verbose'] = False ## print what you're removing line by line
- options['help'] = False ## Print help
- options['version'] = False ## Print version
- return options
- def dup_finder(aString):
- '''
- This strips the string of its extension, then looks for a number.
- '''
- ## The duplicate counter.
- dupCount = 0
- ## Remove all characters up to and including the first period
- ## Remember that this is supposed to be a reversed filename string,
- ## so the extension comes first ('vlf.oediv_a')
- aString = aString.replace(aString[0:aString.index('.')+1],'',1)
- for i in aString:
- try:
- dupCount = int(i)
- dupCount += 1
- break
- except ValueError:
- pass
- return dupCount
- def string_fixer(stringToBeFixed):
- '''
- Fixes a string with weird characters
- '''
- ## Convert the entire string to lowercase
- newStr = stringToBeFixed.lower()
- ## Rename "d&d" to 'dnd'
- newStr = newStr.replace('d&d','dnd',-1)
- ## Remove any verboten characters
- for v in VERBOTEN:
- newStr = newStr.replace(v, '', -1)
- for l in LESS_VERBOTEN:
- newStr = newStr.replace(l, '_', -1)
- ## Now that all the verboten characters have been removed, you can
- ## optionally replace 'dnd' with 'd&d' again. By default, I assume
- ## this isn't wanted. If you do want to do this, uncomment the following
- ## line:
- #newStr = newStr.replace('dnd', 'd&d', -1)
- ## Strip leading and trailing whitespace
- newStr = newStr.strip()
- ## Replaces spaces with underscores
- newStr = newStr.replace(' ','_',-1)
- return newStr
- def tag_fixer(tagToBeFixed):
- '''
- Similar to string_fixer, except especially for tags
- '''
- newTag = tagToBeFixed
- ## Replace some punctuation with what the guy on the forum said
- newTag = newTag.replace('&', '&', -1) ## It's important that this be 1st
- newTag = newTag.replace('"','"', -1)
- newTag = newTag.replace("'",''', -1)
- newTag = newTag.replace('<', '<', -1)
- newTag = newTag.replace('>', '>', -1)
- for v in VERBOTEN:
- if v == '&' or v == ';':
- pass
- else:
- newTag = newTag.replace(v, '', -1)
- ## Strip leading and trailing whitespace
- newTag = newTag.strip()
- if SPACES_TO_COMMAS == True:
- newTag = newTag.replace(' ',',',-1)
- else:
- ## If USE_UNDERSCORES == True, do so. Otherwise, enclose w/quotes
- if USE_UNDERSCORES == True:
- newTag = newTag.replace(' ', '_', -1)
- else:
- newTag = '"%s"' % newTag
- ## Return the 'finished' tag
- return newTag
- def renamer(origName, fileNameListCheck):
- '''
- Renames the files in the list
- WARNING: This function is somewhat broken currently. Make sure that you
- don't have any files with identical names, or names that WILL be identical
- after their names have been 'corrected'
- '''
- newName = string_fixer(origName)
- ## We should be good by this point, but it's safest to check that the
- ## current filename we're working on isn't a duplicate. If it is, number
- ## it.
- ## To ensure the list is 'cleared' of duplicates. We assume that there
- ## are, to start with.
- doneChecking = 1
- while (doneChecking > 0):
- ## This will change if duplicates are found
- doneChecking = 0
- for n in fileNameListCheck:
- if newName == n:
- ## Create a reversed copy of newName, so that we can get the
- ## last period before the filename extension. There might be a
- ## better way to do this, but .... meh.
- revNewName = newName[::-1]
- ## This finds the current 'count' of the possible duplicate
- dupCount = dup_finder(revNewName)
- # if dupCount == 0:
- # ## Put '2' right after (before) the suffix
- # revNewName = revNewName.replace('.','.2_',1)
- # else:
- # ## Put the duplication interation right after (before)
- # ## the extension
- # revNewName =revNewName.replace('.','.%s_',1) %str(dupCount)
- newName = revNewName[::-1]
- fileNameListCheck.remove(n)
- ## Increment doneChecking
- doneChecking += 1
- ## Finally, return newName
- return newName
- def rename_files():
- '''
- This function will rename all of the files. Go figure. This is not a very
- 'smart' program, so (thus far) it will only work with files in the present
- working directory.
- '''
- ## The lists into which we'll put all of our 'corrected' filenames
- fileNameListCheck = []
- fileNameList = []
- ## A list of all the files in the current working directory
- listOfFiles = os.listdir(os.getcwd())
- ## Removes anything that isn't in the list of valid files to be renamed
- ## (in other words, anything that isn't a video file)
- lof = []
- for i in listOfFiles:
- for v in VALID:
- if v in i:
- lof.append(i)
- listOfFiles = lof
- ## Create the first list of filenames to check against
- for f in lof:
- newName = string_fixer(f)
- fileNameListCheck.append(newName)
- ## Now that we've got our first list, we go through the PWD list again
- ## checking against that first list for duplicates
- for f in listOfFiles:
- newName = renamer(f, fileNameListCheck)
- fileNameList.append(newName)
- ## Here, we ensure that the lists are the same length. If they are not,
- ## something went terribly wrong and the program needs to exit before
- ## any damage is done.
- if len(listOfFiles) == len(fileNameList):
- pass
- else:
- print("Error: Mismatched filename lists. Quitting.")
- sys.exit()
- ## And now we return the necessary lists
- return listOfFiles, fileNameList
- def move_files(listOfFiles, fileNameList, options):
- '''
- This does the actual moving (renaming) of the files on the operating system
- '''
- for f in listOfFiles:
- if options['verbose'] == True:
- print("%s ---> %s" % (f, fileNameList[listOfFiles.index(f)]))
- shutil.move(f, fileNameList[listOfFiles.index(f)])
- def generate_xml(fileData):
- '''
- This function does the actual XML generation
- '''
- xml = """
- <?xml version="1.0" encoding="UTF-8"?>
- <file_upload>
- <report>%s</report>
- <item>
- <filename>%s</filename>
- <title>
- <![CDATA[%s]]>
- </title>
- <duration>%s</duration>
- <tags>%s</tags>
- <age>%s</age>
- <description>
- <![CDATA[%s]]>
- </description>
- <activation_date>%s</activation_date>
- </item>
- <item>
- <filename>%s</filename>
- <title>
- <![CDATA[%s]]>
- </title>
- <duration>%s</duration>
- <tags>%s</tags>
- <age>%s</age>
- <description>
- <![CDATA[%s]]>
- </description>
- <activation_date>%s</activation_date>
- </item>
- </file_upload>
- """ % (REPORT,
- fileData['name'],
- fileData['title'],
- fileData['duration'],
- fileData['tags'],
- fileData['ageCap'],
- fileData['description'],
- fileData['activationDate'],
- fileData['name'],
- fileData['title'],
- fileData['duration'],
- fileData['tags'],
- fileData['ageCap'],
- fileData['description'],
- fileData['activationDate'])
- return xml
- def generate_tag_list(aStr):
- '''
- This takes a string and creates a list of tags, with a new tag happening
- after every comma
- '''
- tagList = []
- ## Grab each tag from the string
- while(len(aStr) > 0):
- try:
- tag = aStr[0:aStr.index(',')]
- aStr = aStr.replace(aStr[0:aStr.index(',')+1],'',1)
- tagList.append(tag)
- except ValueError:
- tag = aStr[0:-1]
- tagList.append(tag)
- aStr = ""
- return tagList
- def get_description(fileName, options):
- '''
- Have the user input a basic description for the file.
- '''
- descStr = """
- Now you'll enter a description for the file. It will look ugly as you type,
- but that's unavoidable (at least, for the effort I'm willing to put in).
- Just type whatever and hit enter when you're done.
- \n
- Note: To use the previously used description, leave this field blank and
- hit enter. To use no description, just put a zero (0) and hit enter.
- """
- print(descStr)
- print("Filename: %s" % fileName)
- queryString = "Description: "
- description = get_input(queryString)
- if description == "":
- description = options['prevDescription']
- elif description == '0':
- description = ""
- return description
- def get_tags(fileName):
- '''
- We let the user enter their own tags manually.
- '''
- ## Empty 'tags' string
- tags = ""
- print('\n\n\n---------------------------', fileName)
- print("\nEnter tags as a comma-separated list:\n")
- if SPACES_TO_COMMAS == True:
- print("(Spaces will be converted to commas)\n")
- else:
- if USE_UNDERSCORES == True:
- print("(Spaces will be converted to underscores)\n")
- else:
- print("(Your tags will be enclosed in quotation marks)\n")
- ## The query string is what the user sees for a prompt
- queryString = "tags: "
- ## Get the input (in this case, comma-separated list of tags)
- print("Filename: ", fileName)
- theInput = get_input(queryString)
- ## Create a tag list according to input
- tagList = generate_tag_list(theInput)
- for tag in tagList:
- tag = tag_fixer(tag)
- ## Add a comma and the fixed tag to the tag string
- tags += ",%s" % tag
- ## Finally, return the tags string
- return tags
- def autogen_tags(fileName):
- '''
- Automatically generate some tags
- '''
- ## As mentioned, this isn't ideal but... whatever.
- tagString = fileName
- for v in VALID:
- if v in tagString:
- tagString = tagString.replace(v, '', -1)
- elif v.upper() in tagString:
- tagString = tagString.replace(v.upper(), '', -1)
- tagString = tagString.replace('_',',',-1)
- tagString = tagString.replace('-',',',-1)
- return tagString
- def xml_the_files(fileNameList, options):
- '''
- This function generates some (less than ideal) metadata for each file
- in the list of files passed to it. Then it creates an XML file for each
- one, named identically to the file except with a .xml extension.
- '''
- for f in fileNameList:
- fileData = {}
- ## Used later
- ft = ""
- ## Set file name
- fileData['name'] = f
- ## Set file size. Disabled by default
- #fileData['fileSize'] = os.stat(f)[6]
- ## Autogenerate some tags
- tags = autogen_tags(f)
- fileData['tags'] = tags
- ## If the user does not want to use any autogenerated tags
- if options['autogen'] == False:
- tags = get_tags(f)
- fileData['tags'] = tags
- ## Here we remove the extension from the filename
- for v in VALID:
- if v in f:
- ft = f.replace(v, '', -1)
- ## Create a fancy title for the CDATA block. God I love Python.
- fancyTitle = ft.title()
- fancyTitle = fancyTitle.replace('_',' ', -1)
- ## Title of the file
- fileData['title'] = fancyTitle
- ## Duration of the video. '-||-' is used in place of actual duration
- fileData['duration'] = "-||-"
- ## The age cap
- fileData['ageCap'] = "0"
- ## If autogen is on, set the description to be the same as the file's
- ## title. Otherwise, have the user manually enter the description
- if options['autogen'] == True:
- fileData['description'] = ft
- else:
- fileData['description'] = get_description(f, options)
- options['prevDescription'] = fileData['description']
- ## Set the file activation date
- fileData['activationDate'] = options['activationDate']
- ## Finally, we generate the actual XML
- xml = generate_xml(fileData)
- ## We get rid of the top newline, just to make it prettier
- xml = xml.replace('\n','',1)
- ## Create a name for the new XML file
- xmlName = "%s%s" % (ft, XML_EXTENSION)
- ## And finally, write it to disk
- try:
- xmlFile = open(xmlName, 'w')
- for line in xml:
- xmlFile.write(line)
- if options["verbose"] == True:
- print("Generating %s" % xmlName)
- xmlFile.close()
- except IOError:
- print("""
- Error: Cannot open %s for writing. Do you have permissions?
- """ % xmlName)
- sys.exit()
- def get_options(options):
- '''
- Get options from the command line
- '''
- for i in sys.argv:
- if i == '-v':
- options['verbose'] = True
- elif i == '--verbose':
- options['verbose'] = True
- elif i == '-h':
- options['help'] = True
- elif i == '--help':
- options['help'] = True
- elif i == '--version':
- options['version'] = 1
- elif i == '--auto':
- options['autogen'] = True
- return options
- def print_help():
- '''
- Print the help
- '''
- helpStr = """
- This script will look through a directory of files (video files, by default)
- and generate an XML file for each one. Each XML file will have some basic
- metadata, which can be automatically generated if you don't mind having
- shitty tags.
- Currently, this script must be run inside the directory where all of the
- files to be read/generated are.
- usage: steel_reserve.py [argument]
- Arguments:
- -h or --help: Print help
- -v or --verbose: Verbosity
- --version: Print version / info
- --auto: Use autogeneration (easiest)
- """
- print(helpStr)
- def print_version():
- '''
- Prints the version stuff
- '''
- versionStr = """
- Program: steel_reserve.py
- Version: 0.8
- License: GPL 3 (http://www.gnu.org/licenses/gpl.html)
- Last edit: 2012-08-23
- Description: Generates XML files for files (video files by default) in
- the current working directory.
- """
- print(versionStr)
- def main():
- '''
- The main function. First we rename all the files as necessary, then we get
- the necessary info about them, then we create the XML files for them.
- '''
- ## Get the options for the program
- options = set_options()
- ## If options were passed on the command line, set them here
- options = get_options(options)
- ## Do the help/version stuff
- if options['help'] == True:
- print_help()
- sys.exit()
- if options['version'] == True:
- print_version()
- sys.exit()
- ## Get the lists of original filenames and their replacements
- listOfFiles, fileNameList = rename_files()
- ## Move (rename) the files
- if options['verbose'] == True:
- print("\n================= RENAMING FILES ================\n")
- move_files(listOfFiles, fileNameList, options)
- ## Generate metadata for each file, then create an XML file for it
- if options["verbose"] == True:
- print("\n=============== GENERATING XML FILES ================\n")
- xml_the_files(fileNameList, options)
- ## One final line to separate output from the prompt
- if options['verbose'] == True:
- print("")
- if __name__ == "__main__":
- main()
Advertisement
Add Comment
Please, Sign In to add comment