Advertisement
Guest User

tag.py

a guest
Oct 23rd, 2016
60
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 8.38 KB | None | 0 0
  1. """
  2.    Created by reddit user /u/notsplat.
  3.    This is share-ware; edit it if you like, tell your friends if you want to. Just leave this header part up here!
  4.    If you want to donate to me, use this link:
  5.    https://greenaddress.it/pay/GA4VAAh9K2xw1UAG8fat9asiCAUcht/
  6. """
  7.  
  8. import eyed3
  9. import os
  10.  
  11. # Change this to your own music library's location.
  12.  
  13. rootdir = u"C:/Users/Username/Music"   # Change me!
  14.  
  15. valid_extensions = [".mp3"]
  16.  
  17. def fix_tags(directory):
  18.     # Loop through files in library location.
  19.     for subdir, dirs, files in os.walk(directory):
  20.         # If we've already done this album, skip.
  21.         if os.path.isfile(os.path.join(subdir, "_ignore")) and subdir != rootdir:
  22.             continue
  23.         elif subdir != rootdir:
  24.             # Make sure it's an album folder.
  25.  
  26.             x = False
  27.            
  28.             for y in os.listdir(subdir):
  29.                 if y[len(y)-4:] in valid_extensions:
  30.                     x = True
  31.             if x:
  32.                 open(os.path.join(subdir, "_ignore"), 'a').close()
  33.  
  34.         # Sort our files so we can set the track number from it.
  35.         sorted(files)
  36.  
  37.         # Just a counter.
  38.         q = 0
  39.  
  40.         for file in files:
  41.             # Try/except for catching errors.
  42.             try:
  43.                 if file[len(file)-4:] not in valid_extensions:
  44.                     continue
  45.  
  46.                 q += 1
  47.  
  48.                 # Load our file for this iteration.
  49.                 audiofile = eyed3.load(os.path.join(subdir, file))
  50.                 print "LOADED:\t" + file + "."
  51.  
  52.                 # If the total discs is one or nil, leave our disc tag empty.
  53.                 if audiofile.tag.disc_num[1] <= 1:
  54.                     audiofile.tag.disc_num = (None, None)
  55.  
  56.                     v = str(q)
  57.  
  58.                     if q < 10:
  59.                         v = "0" + v
  60.  
  61.                     audiofile.tag.track_num = (v, audiofile.tag.track_num[1])
  62.  
  63.                 # Otherwise, add trailing zeroes to disc number.
  64.                 else:
  65.                     # Convert to str to read.
  66.                     d = str(audiofile.tag.disc_num)
  67.  
  68.                     # Initialise variables for disc index and total, respectively.
  69.                     i, t = "", ""
  70.  
  71.                     # Should it be a tuple, strip it of its parentheses and use the resulting string to read from.
  72.                     if type(eval(d)) == tuple:
  73.                         s = d.lstrip("(").rstrip(")")
  74.  
  75.                         # Read our index from the tuple.
  76.                         i = s[0:s.find(",")]
  77.  
  78.                         # Remember, trailing zeroes are not necessary for indices of 10 or above.
  79.                         if int(i) < 10:
  80.                             # Neither is it necessary to have multiple trailing zeroes for our disc numbers.
  81.                             if i[0] != "0":
  82.                                 i = "0" + i
  83.  
  84.                     # Set our disc number; bizarrely, the title automatically trails given a track index which is trailed. This still has to be saved later.
  85.                     audiofile.tag.disc_num = (i, audiofile.tag.disc_num[1])
  86.  
  87.                 # String-ify the track number property.
  88.                 v = str(audiofile.tag.track_num)
  89.  
  90.                 # Initialise some variables for index and total amount of tracks.
  91.                 i, t = "", ""
  92.  
  93.                 # If there is not already a trailing zero then ...
  94.                 if v[0] != "0":
  95.                     # Should our track number be a tuple, strip its parentheses and make it readable as a string.
  96.                     if type(eval(v)) == tuple:
  97.                         s = v.lstrip("(").rstrip(")")
  98.  
  99.                         # Find our index from this string-ified tuple.
  100.                         i = s[0:s.find(",")]
  101.  
  102.                         # Once again, we do not need to trail zeroes unless our track is between 0-9, or is already trailed.
  103.                         if int(i) < 10:
  104.                             if i[0] != "0":
  105.                                 i = "0" + i
  106.  
  107.                     # Set our track number. As above, no need to parse or rewrite the total.
  108.                     audiofile.tag.track_num = (i, audiofile.tag.track_num[1])
  109.  
  110.                 # Rename and re-tag untitled tracks.
  111.                 try:
  112.                     # Firstly, lower() the title, and see if it is titled like a typical untitled track.
  113.                     if audiofile.tag.title.lower() == "[untitled]" or audiofile.tag.title.lower() == "untitled":
  114.                         # We save the title tag with unicode-encoded strings.
  115.                         audiofile.tag.title = u"Untitled"
  116.                 except TypeError:
  117.                     # If it is unreadable as a string, then that probably warrants that it be titled blank, too.
  118.                     audiofile.tag.title = u"Untitled"
  119.  
  120.                 # Save our tracks and their tags; the fruits of our labour.
  121.                 # We use os.path.normpath(path) to localise the file location's string to the directory structure of the host system. This is to avoid quite unlikely but pretty annoying errors that would occur from using "/" on a Windows System. Screw you, Microsoft.
  122.                 audiofile.tag.save(
  123.                     os.path.normpath(os.path.join(subdir, file)),
  124.                     eyed3.id3.ID3_V2_3
  125.                 )
  126.  
  127.                 # We print our result!
  128.                 print u"SAVED: \t" + file + u"."
  129.  
  130.             except AttributeError as e:
  131.                 # We don't want to print attribute errors when the file isn't even an mp3. This happens when our function loops through some other files that may be in the directory -- for example, "folder.png" or similar.
  132.                 print "AttributeError:\t" + str(e)
  133.  
  134.             # Print our other exceptions.
  135.             except IOError as e:
  136.                 print "IOError:\t" + str(e)
  137.  
  138.             except UnicodeEncodeError as e:
  139.                 print "UnicodeEncodeError:\t" + str(e)
  140.  
  141. def capitalise_title(title):
  142.     # List the words we want in lower-case.
  143.     words = ["a", "an", "at", "and", "by", "for", "in", "of", "on", "to", "the"]
  144.  
  145.     # Split the title into a list of words to check.
  146.     new_title = title.lower().split(" ")
  147.  
  148.     for i, word in enumerate(new_title):
  149.         # Always capitalise the first letter of the title.
  150.         # We also capitalise if the word is not in the above list.
  151.         if i == 0 or not word in words:
  152.             new_title[i] = word[0].upper() + word[1:].lower()
  153.         else:
  154.             new_title[i] = word.lower()
  155.  
  156.     # Create a buffer and write to our new_title.
  157.     _new_title = new_title
  158.     new_title = ""
  159.  
  160.     for i, word in enumerate(_new_title):
  161.         new_title += word
  162.  
  163.         # We don't want a space to be the last character of the title.
  164.         if i < len(_new_title) - 1:
  165.             new_title += " "
  166.  
  167.     return new_title
  168.  
  169. def fix_folders(directory):
  170.     # Loop through each artist folder.
  171.     for artist in os.listdir(directory):
  172.         # Just to make the join()'s a little easier.
  173.         current_folder = os.path.join(directory, artist)
  174.  
  175.         # Skip to next folder if this is not a directory.
  176.         if not os.path.isdir(current_folder):
  177.             continue
  178.  
  179.         # Loop through the album folders.
  180.         for album in os.listdir(current_folder):
  181.             # Skip if not a directory.
  182.             if not os.path.isdir(os.path.join(current_folder, album)):
  183.                 continue
  184.  
  185.             # Skip to next album if "ignore" file exists.
  186.             if os.path.isfile(os.path.join(os.path.join(current_folder, album), "ignore")):
  187.                 continue
  188.  
  189.             # Capitalise the title correctly.
  190.             new_album = capitalise_title(album)
  191.  
  192.             # No need to rename if it's identical to the previous title.
  193.             if new_album != album:
  194.                 os.rename(
  195.                     os.path.join(current_folder, album),
  196.                     os.path.join(current_folder, new_album)
  197.                 )
  198.  
  199.         # We do the album stuff first for each artist, then re-capitalise the artist's title.
  200.         new_artist = capitalise_title(artist)
  201.  
  202.         if new_artist != artist:
  203.             os.rename(
  204.                 os.path.join(directory, artist),
  205.                 os.path.join(directory, new_artist)
  206.             )
  207.  
  208. def main():
  209.     fix_tags(rootdir)
  210.     fix_folders(rootdir)
  211.  
  212. # Call main().
  213. if __name__ == '__main__':
  214.     main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement