Wednesday, October 07, 2009

Take the Red PIL Neo...

OK - so I have a directory filled with around a thousand fonts.  Which is a Good Thing.  They're even separated into sub directories based on the first letter of the font name.  So what's the problem you ask?  All of this seems like good stuff.  Well, the file names themselves are complete gibberish.  gobbledygook.  garbage.  Which is a Bad Thing.  I'm not installing all 1000 fonts.  And I sure as hell ain't gonna rename them by hand.  Forget it.

So, enter magic and PIL.  Python's magic module allows file typing, and PIL's ImageFont module lets you grab the font information.  An violá we have a font renamer in Python:


#!/usr/bin/env python
#
#  font_renamer.py - utility to rename fonts based on name.
#
#  WARNING!!!  This script renames your fonts IN SITU.  If in doubt,
#  make a copy of the fonts directy first BEFORE you run the script.
#  You have been warned.
#
#  Depends on PIL and magic (not magic pills).
#
#  A big thank you to the python-list, who provided the snippets
#  I needed to piece this together!
#
#  (C) 2009 Chris Mohler
#
#  This program is free software: you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation, either version 3 of the License, or
#  (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.

#  You should have received a copy of the GNU General Public License
#  along with this program.  If not, see .

import sys, os, magic

from PIL import ImageFont

def rename_ttf (file):
    # open font with PIL
    f = ImageFont.truetype(file, 1)

    # fashion a new file name - family + style
    newfilename = f.font.family.replace(' ', '_') + '_'
    newfilename = newfilename + f.font.style.replace(' ','_') + ".ttf"

    # bust the old filename and path up
    filet = os.path.split(file)

    # new tuple with old path and new filename
    newfilet = filet[0:-1] + (newfilename,)

    # join the tuple together
    newfile = os.sep.join(str(x) for x in newfilet)
   
    # rename the font
    os.rename(file,newfile)


def main() :
   
    # we only want one argument, and it should be a dir
    if len(sys.argv) == 2:
        if os.path.isdir(sys.argv[1]):
            folder = sys.argv[1]
        else:
            print "Usage: font_renamer.py directory"
            exit
    else:
        print "Usage: font_renamer.py directory"
        exit

    # walk the dir
    for root, dir, files in os.walk(folder):
        for file in files:
            # initialize magic (really - it IS magic)
            m = magic.open(magic.MAGIC_NONE)
            m.load()
           
            # find the file type
            type = m.file(os.path.join(root, file))

            # if it's a TTF, then let's rename it
            if type == "TrueType font data":
                rename_ttf(os.path.join(root, file))

# hold on to your ass, here we go
main()



I tested on Ubuntu 9.04, but it uses the os module -  so with any luck you MS/OSX folks have a free batch font renamer as well.  Heed the warning in the script well my friends, heed it well.   Don't come crying to me if this thing eats your fonts or your kittens.

GPL v3 is probably overkill, but at least it's not ambigous.  And hey - if this saves your ass (or an hour of your time), my Paypal account is never full :)