3451cc25 |
#!/usr/bin/env python
# Copyright (c) 2015 Edward Langley
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# Neither the name of the project's author nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
'''Sorts music into my preferred directory layout.
Usage: find -name '*.mp3' -o '*.m4a' . . . | python sorter.py <destination_directory>
Requires mutagen for tag handling (and, therefore, taglib)'''
|
1b985a35 |
import os
|
84c56ae8 |
import shutil
|
1b985a35 |
import string
import mutagen
import argparse
parser=argparse.ArgumentParser()
parser.add_argument('destination')
args = parser.parse_args()
destination = args.destination
|
a46f1513 |
print('copying music to, %s' % destination)
|
1b985a35 |
import sys
class PathFinder(object):
def __init__(self):
pass
|
a46f1513 |
def construct_tag_map(self, data):
tag_map = {}
for (tag, _) in data.tags:
tag_map[tag.lower()] = tag
return tag_map
|
1b985a35 |
def get_path(self, data, orig_name):
|
a46f1513 |
tag_map = self.construct_tag_map(data)
print(tag_map, tag_map['title'], data.get(tag_map['title']))
|
1b985a35 |
orig_name = orig_name.rpartition('.')[0]
|
a46f1513 |
title=self.clean(data.get(tag_map['title'], ['Unknown Title'])[0])
|
1b985a35 |
if title.strip() == '': title = orig_name
|
a46f1513 |
album=self.clean(data.get(tag_map['album'], ['Unknown Album'])[0])
|
1b985a35 |
if album.strip() == '': album = 'Unknown Album'
|
a46f1513 |
if 'albumartist' in data: artist = data[tag_map['albumartist']][0]
elif 'performer' in data: artist = data[tag_map['performer']][0]
elif 'conductor' in data: artist = data[tag_map['conductor']][0]
else: artist = data.get(tag_map['artist'], ['Unknown Artist'])[0]
|
1b985a35 |
artist = self.clean(artist)
if artist.strip() == '': artist = 'Unknown Artist'
|
a46f1513 |
tracknumber=self.clean(data.get(tag_map['tracknumber'], ['--'])[0])
|
1b985a35 |
if tracknumber != '--':
try:
tracknumber = tracknumber.partition('_')[0]
tracknumber = '%02d' % int(tracknumber)
except ValueError:
pass
|
a46f1513 |
discnumber=self.clean(data.get(tag_map['discnumber'], ['--'])[0].partition('/')[0])
print(f'discnumber is: {discnumber}')
if discnumber.strip() not in {'', '--'}: discnumber = '%02d' % int(discnumber)
|
1b985a35 |
result =[ os.path.join(artist[0].upper(),artist,album), '%s_%s' % (tracknumber, title) ]
|
a46f1513 |
if discnumber.strip() not in {'', '--'}:
|
1b985a35 |
result[1] = '%s_%s' % (discnumber, result[1])
return result
validchars = frozenset('_.- %s%s' % (string.ascii_letters, string.digits))
def clean(self, strin):
strin = ''.join((c if c in self.validchars else " ") for c in strin)
strin = '_'.join(strin.split())
if len(strin) > 40:
pa = strin[:28]
pb = strin[-31:]
strin = '...'.join([pa,pb])
return strin
pf = PathFinder()
for line in sys.stdin:
line = line.strip()
try:
file = mutagen.File(line, easy=True)
x = 0
suf = ''
path, name = pf.get_path(file, os.path.basename(line))
ext = line.rpartition('.')[-1]
path = os.path.join(destination, path)
|
a46f1513 |
checkname = '%s.%s' % ('__'.join([_f for _f in [name, suf] if _f]), ext)
|
1b985a35 |
|
a46f1513 |
while os.path.exists(os.path.join(path, '%s.%s' % ('__'.join([_f for _f in [name, suf] if _f]), ext))):
|
1b985a35 |
x += 1
suf = '%02d' % x
|
a46f1513 |
name = '%s.%s' % ('__'.join([_f for _f in [name, suf] if _f]), ext)
|
1b985a35 |
try:
os.makedirs(path)
|
a46f1513 |
except OSError as e:
|
1b985a35 |
if e.errno == 17:
pass
else:
raise
|
a46f1513 |
print(os.path.join(path, name))
|
84c56ae8 |
shutil.copy(line, os.path.join(path, name))
|
a46f1513 |
except Exception as e:
print('Error Processing: %s' % line,e, file=sys.stderr)
print('Error Processing: %s' % line,e)
|