summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDennis Fink2018-04-07 10:31:36 +0200
committerDennis Fink2018-04-07 10:31:36 +0200
commit38d0ad688232ad5dc826d813e0e56edb3d372820 (patch)
treee61b32bcd1ca4d803b370cbc0ab98e49c774eccd
parenta925e57a485ba652d3125394ee66f8ec44845fc4 (diff)
downloadpatternutils-38d0ad688232ad5dc826d813e0e56edb3d372820.tar.gz
patternutils-38d0ad688232ad5dc826d813e0e56edb3d372820.zip
Added the tmv command
Diffstat (limited to '')
-rw-r--r--patternutils/commands/tmv.py90
-rw-r--r--setup.py1
2 files changed, 91 insertions, 0 deletions
diff --git a/patternutils/commands/tmv.py b/patternutils/commands/tmv.py
index e69de29..145a261 100644
--- a/patternutils/commands/tmv.py
+++ b/patternutils/commands/tmv.py
@@ -0,0 +1,90 @@
+import json
+import os.path
+import shutil
+
+import click
+
+from .. import template
+from .. import config
+
+
+def move_file(old_filename: str, new_filename: str) -> None:
+ # Create new directories if needed
+ dirs = os.path.dirname(new_filename)
+ if dirs:
+ os.makedirs(dirs, exist_ok=True)
+
+ shutil.move(old_filename, new_filename)
+
+
+@click.command(context_settings={'help_option_names': ('-h', '--help', '-?')})
+@click.option('-i', '--interactive', is_flag=True, default=False,
+ help='prompt before renaming files')
+@click.option('-f', '--force', is_flag=True, default=False,
+ help='force rename')
+@click.option('-t', '--template-engine', default='python', type=click.Choice(['python', 'jinja2']),
+ help='select the template engine to use')
+@click.option('-p', '--use-predefined-template', is_flag=True, default=False,
+ help='use predefined template')
+@click.option('--read-from', default='-', type=click.File('r'))
+@click.option('--abort-on-path-exist', is_flag=True, default=False,
+ help='exit if a renamed path already exists')
+@click.option('-n', '--dry-run', is_flag=True, default=False,
+ help='perform a trial run with no changes made')
+@click.option('-v', '--verbose', is_flag=True, default=False,
+ help='explain what is being done')
+@click.version_option()
+@click.argument('output-pattern')
+def tmv(
+ output_pattern: str,
+ interactive: bool,
+ force: bool,
+ template_engine: str,
+ abort_on_path_exist: bool,
+ use_predefined_template: bool,
+ read_from: click.File,
+ dry_run: bool,
+ verbose: bool,
+) -> None:
+
+ try:
+ data = json.load(read_from) # type: ignore
+ except json.JSONDecodeError:
+ click.secho('JSON not valid!', fg='red', err=True)
+ raise SystemExit
+
+ if use_predefined_template:
+ output_pattern, template_engine = config.load_template(output_pattern, 'tmv')
+
+ try:
+ render = template.get_render_function(output_pattern, engine=template_engine)
+ except RuntimeError:
+ click.secho('jinja2 not installed!', fg='red', err=True)
+ raise SystemExit
+
+ new_filenames = dict((entry['_abspath'], render(**entry)) for entry in data)
+
+ has_existing = False
+ non_existing = {}
+ for old, new in new_filenames.items():
+ if os.path.exists(new):
+ click.secho('{} does exist!'.format(new), fg='red', err=True)
+ has_existing = True
+ else:
+ non_existing[old] = new
+
+ if has_existing and abort_on_path_exist:
+ raise SystemExit
+
+ if force:
+ files_to_move = new_filenames.items()
+ else:
+ files_to_move = non_existing.items()
+
+ for old, new in files_to_move:
+ if verbose or interactive:
+ click.echo('{} -> {}'.format(old, new))
+
+ if not (interactive and not click.confirm('Is the match correct?')):
+ if not dry_run:
+ move_file(old, new)
diff --git a/setup.py b/setup.py
index bad74b8..2dfebe4 100644
--- a/setup.py
+++ b/setup.py
@@ -29,6 +29,7 @@ setup(
'console_scripts': [
'pmatch=patternutils.commands.pmatch:pmatch',
'targs=patternutils.commands.targs:targs',
+ 'tmv=patternutils.commands.tmv:tmv',
],
},
install_requires=REQUIRED,