Skip to content

Instantly share code, notes, and snippets.

@torbiak
Last active April 17, 2016 19:01
Show Gist options
  • Save torbiak/80c05e4b4b965082d7cb to your computer and use it in GitHub Desktop.
Save torbiak/80c05e4b4b965082d7cb to your computer and use it in GitHub Desktop.
Guess Tag From Filename
#!/usr/bin/env python
# Guess Tags From Filename, using python and mutagen.
import mutagen
from mutagen.easyid3 import EasyID3
import re
import os.path
import sys
def tag(filename, regex, constant_tags):
basename = os.path.basename(filename)
basename = basename[:basename.rindex('.')] # strip extension
m = regex.search(basename)
if not m:
raise Exception("Regex {} doesn't match {}".format(regex.pattern, filename))
f = mutagen.File(filename, easy=True)
for name, i in regex.groupindex.items():
f[name] = m.group(i)
for k, v in constant_tags.items():
f[k] = v
f.save()
def pattern_to_regex(pattern):
# Escape everything, but then unescape angle brackets to make conversion
# into a regex easier.
# TODO: Imbalanced angle brackets in the pattern behave poorly.
pattern = re.escape(pattern)
pattern = re.sub(r'\\([<>])', r'\1', pattern)
pattern = re.sub('(<[^>]*>)', r'(?P\1.*?)', pattern)
pattern += '$'
regex = re.compile(pattern)
tags = regex.groupindex.keys()
invalid_tags = [t for t in tags if t not in EasyID3.valid_keys]
if invalid_tags:
raise Exception('Invalid tag names: {}'.format(invalid_tags))
return regex
if __name__ == '__main__':
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('-p', '--pattern', default='<artist> - <title>', help='filename pattern, eg: <artist> - <title>. An empty pattern can be specified so only constant tags are applied.')
parser.add_argument('-t', '--tag', metavar='TAGNAME=VALUE', action='append', default=[], help='specify a constant tag')
parser.add_argument('--valid-tags', action='store_true', help="print valid tag names for mutagen's EasyMP3 interface")
parser.add_argument('files', nargs='*')
args = parser.parse_args()
if args.valid_tags:
print '\n'.join(sorted(EasyID3.valid_keys.keys()))
sys.exit(0)
constant_tags = {}
invalid_tags = []
for t in args.tag:
k, v = t.split('=', 1)
if k not in EasyID3.valid_keys:
invalid_tags.append(k)
constant_tags[k] = v
if invalid_tags:
raise Exception('Invalid tag names: {}'.format(invalid_tags))
regex = pattern_to_regex(args.pattern)
for f in args.files:
tag(f, regex, constant_tags)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment