diff --git a/cli.py b/cli.py new file mode 100755 index 0000000..cb23b9b --- /dev/null +++ b/cli.py @@ -0,0 +1,73 @@ +#!/usr/bin/env python3 +import sys +from os import rename +from argparse import ArgumentParser + +from normalisename import Normalisename + + +if __name__ == '__main__': + # parse arguments + parser = ArgumentParser(description='Eliminate funky stuff from filenames.') + parser.add_argument( + '--separator', '-s', type=str, nargs='?', default='_', + help='Set separator to use (to replace spaces with).' + ) + parser.add_argument( + '--allow', '-a', type=str, nargs='?', action='append', + help='Specify a special character to allow (it will not be removed).' + ) + parser.add_argument( + '--disallow', '-d', type=str, nargs='?', action='append', + help='Specify a special character to disallow (it will removed).' + ) + parser.add_argument( + '--whitelist', '-w', type=str, + help='Overwrite default whitelist (format: whitespace separated string).' + ) + + mgroup = parser.add_mutually_exclusive_group() + mgroup.add_argument( + '--dryrun', '-n', action='store_true', + help='Do not touch anything, just tell me what would change!' + ) + mgroup.add_argument( + '--funky', '-f', action='store_true', + help='List filenames with special characters' + ) + parser.add_argument( + 'files', type=str, nargs='+', + help='File(s) to normalise the name of (relative or absolute path).' + ) + + args = parser.parse_args() + + # verify arguments + if args.disallow: + if args.separator in args.disallow: + sys.exit('Disallowing your chosen separator makes no sense!') + + # declare special characters that will not be removed (spaces are handled elsewhere) + whitelist = {' ', '.', '-'} + if args.whitelist: + whitelist = set(args.whitelist.split()) + + # modify whitelist based on arguments + whitelist.add(args.separator) + if args.allow: + whitelist = whitelist.union(set(args.allow)) + if args.disallow: + whitelist = whitelist.difference(set(args.disallow)) + + # define operations + listchanges = lambda a, b: print('{}{} --> {}'.format(a, ' '*(60-len(a)), b)) + listfunky = lambda a, b: print(a) + + operation = rename + if args.dryrun: + operation = listchanges + elif args.funky: + operation = listfunky + + # do what needs to be done + Normalisename(operation, args.separator, whitelist)(args.files) diff --git a/normalisename.py b/normalisename.py index 7fed33e..ff79bd1 100755 --- a/normalisename.py +++ b/normalisename.py @@ -1,14 +1,16 @@ -#!/usr/bin/env python3 -from unidecode import unidecode -from os import rename from os.path import basename, dirname from os.path import join as joinpath -from re import sub as substitute -from argparse import ArgumentParser -from sys import exit +from re import sub + +from unidecode import unidecode -class normalisename: +class Normalisename: + def __init__(self, operation, separator, whitelist): + self._operation, self.operation = None, operation + self._separator = separator + self._whitelist = set(whitelist) + @property def operation(self): return self._operation @@ -27,70 +29,23 @@ class normalisename: def whitelist(self): return self._whitelist - def __init__(self, operation, separator, whitelist): - self._operation = None - self.operation = operation - self._separator = separator - self._whitelist = set(whitelist) - def __call__(self, files): for path in files: if not self.check_normal(path): - dir = dirname(path) - file = basename(path) - normalpath = joinpath(dir, self.normalname(file)) - self.operation(path, normalpath) + directory = dirname(path) + filename = basename(path) + normalpath = joinpath(directory, self.normalname(filename)) + self.operation(path, normalpath) # pylint: disable=not-callable - def check_normal(self, file): - file = basename(file) - return file == self.normalname(file) + def check_normal(self, filename): + filename = basename(filename) + return filename == self.normalname(filename) def normalname(self, filename): - return unidecode(''.join(ch for ch in substitute('\s+', self.separator, filename) - if ch.isalnum() - or ch in self.whitelist)) - - -if __name__ == '__main__': - # parse arguments - parser = ArgumentParser(description='Eliminate funky stuff from filenames.') - parser.add_argument('--separator', '-s', type=str, nargs='?', default='_', - help='Set separator to use (to replace spaces with).') - parser.add_argument('--allow', '-a', type=str, nargs='?', action='append', - help='Specify a special character to allow (it will not be removed).') - parser.add_argument('--disallow', '-d', type=str, nargs='?', action='append', - help='Specify a special character to disallow (it will removed).') - parser.add_argument('--whitelist', '-w', type=str, - help='Overwrite default whitelist (format: whitespace separated string).') - mgroup = parser.add_mutually_exclusive_group() - mgroup.add_argument('--dryrun', '-n', action='store_true', - help='Do not touch anything, just tell me what would change!') - mgroup.add_argument('--funky', '-f', action='store_true', - help='List filenames with special characters') - parser.add_argument('files', type=str, nargs='+', - help='File(s) to normalise the name of (relative or absolute path).') - args = parser.parse_args() - - # verify arguments - if args.disallow: - if args.separator in args.disallow: exit('Disallowing your chosen separator makes no sense!') - - # declare special characters that will not be removed (spaces are handled elsewhere) - whitelist = {' ', '.', '-'} - if args.whitelist: whitelist = set(args.whitelist.split()) - - # modify whitelist based on arguments - whitelist.add(args.separator) - if args.allow: whitelist = whitelist.union(set(args.allow)) - if args.disallow: whitelist = whitelist.difference(set(args.disallow)) - - # define operations - listchanges = lambda a, b: print('{}{} --> {}'.format(a, ' '*(60-len(a)), b)) - listfunky = lambda a, b: print(a) - - operation = rename - if args.dryrun: operation = listchanges - elif args.funky: operation = listfunky - - # do what needs to be done - normalisename(operation, args.separator, whitelist)(args.files) + return unidecode( + ''.join( + ch for ch in sub(r'\s+', self.separator, filename) + if ch.isalnum() + or ch in self.whitelist + ) + )