I've been using the open source book management program Calibre to keep track of my ebook collection. Among other features, it allows downloading of metadata including tags for the books. However, this metadata isn't available outside the Calibre app.
To run the script, you will need to download the Openmeta binary, and install Calibre's command line tools. This can be accomplished by choosing
Preferences > Miscellaneous > Install Command Line Tools
in Calibre.app or add /Applications/calibre.app/Contents/MacOS to your $PATH variable.
The script uses the `which` command to locate the required binaries. It makes a system call to the calibredb program to get the list of books in the current library and extract the tags. Then it calls the openmeta program to write the tags.
import os import sys import subprocess import re def runshell(command): """ Runs the given shell command and returns an array containing the lines from stdout """ p = subprocess.Popen(command, stdout=subprocess.PIPE) (stdout, stderr) = p.communicate() return stdout.splitlines() def quotedspaces(array): """ Takes all the array elements that have spaces and returns a new array with those elements quoted """ n =  for a in array: if ' ' in a: n.append("'" + a + "'") else: n.append(a) return list(set(n)) # removes duplicates def checkpath(mypath): """ Check to make sure the path exists """ return os.path.exists(mypath) def openmeta(path, tags): """Given a filename and array of tags calls openmeta to tag the file with metadata print result """ # get real pathname print 'setting tags for ' + path.split('/')[-1] ar = [openmetapath, '-s'] ar.extend(tags) ar.extend(['-p', path]) # call the shell script result = runshell(ar) return result calibrepath = runshell(['which', 'calibredb']) openmetapath = runshell(['which', 'openmeta']) libraries = ['Personal', 'Technical'] def main(): ''' Reads the tags from Calibre database and writes to the files using openmeta ''' if not checkpath(calibrepath): print "The calibre binary doesn't exist at " + calibrepath sys.exit(-1) if not checkpath(openmetapath): print "The openmeta binary doesn't exist at " + openmetapath sys.exit(-1) calibrecommand = [ calibrepath, 'list', '-f', 'formats', '-w', '100000', ] lines = [l.strip() for l in runshell(calibrecommand) if re.match('[0-9]', l)] for x in lines: (num, y) = x.strip().split(None, 1) files = y[1:-1].split(',/') if files == '': continue metacmd = [calibrepath, 'show_metadata', num] meta = (runshell(metacmd))[22:] tags = quotedspaces([z.strip() for z in meta.split(',')]) for f in files: if f != '/': f = '/' + f openmeta(f, tags) if __name__ == '__main__': main()