logger = logging.getLogger(__name__)
parser = config.add_commandline_args(
f'Dedup Files ({__file__})',
- 'Deduplicate files based on content in a directory or recursively',
+ 'Deduplicate files based on their contents below (one or more) directory(ies) [and, optionally, recursively]',
)
parser.add_argument(
- 'start_dirs',
+ 'root_dir',
type=str,
- nargs='*',
- help='Filespec (glob) of starting directory',
+ nargs='+',
+ help='Filespec (glob) of root directory at which to operate, may include several',
)
parser.add_argument(
'-n',
'-R',
'--recursive',
action='store_true',
- help='Traverse recursively',
+ help='Traverse recursively below root directory(ies)',
)
parser.add_argument(
'-l',
'--link',
action='store_true',
- help='Instead of deleting duplicates, create symbolic links',
+ help='Instead of deleting identified duplicates, create symbolic link back to first source',
)
sizes = defaultdict(list)
dry_size = 0
- for spec in config.config['start_dirs']:
+ for spec in config.config['root_dir']:
if config.config['recursive']:
filez = file_utils.get_files_recursive(spec)
else:
assert not file_utils.is_symlink(dupe)
if config.config['dry_run']:
- print(f'{filename} == {dupe}.')
+ print(f'{filename} == {dupe} (WOULD DELETE {dupe})')
+ if config.config['link']:
+ print(
+ f'{filename} <- {dupe} (WOULD SYMLINK {dupe} to {filename})'
+ )
dry_size += file_utils.get_file_size(dupe)
else:
assert len(filename) >= len(dupe)
saved = filename
killed = dupe
- print(f'{killed} == {saved} -- DELETED')
+ print(f'{killed} == {saved} (DELETED {killed})')
logger.info('Deleting %s', killed)
os.remove(killed)
if config.config['link']:
+ print(f'{saved} <- {killed} (SYMLINK)')
logger.info('Creating symlink from %s -> %s', saved, killed)
os.symlink(saved, killed)
filename = saved
return False
@staticmethod
- def print_usage() -> None:
- """Prints the normal help usage message out."""
- ARGS.print_help()
+ def usage() -> str:
+ """
+ Returns:
+ full program usage help text as a string.
+ """
+ return ARGS.format_help()
@staticmethod
- def usage() -> str:
+ def short_usage() -> str:
"""
Returns:
- program usage help text as a string.
+ program short usage text as a string.
"""
return ARGS.format_usage()
+ @staticmethod
+ def print_usage() -> None:
+ """Prints the full help usage message out."""
+ print(config.usage())
+
+ @staticmethod
+ def print_short_usage() -> None:
+ """Prints a short usage/help message."""
+ print(config.short_usage())
+
@staticmethod
def _reorder_arg_action_groups_before_help(entry_module: Optional[str]):
"""Internal. Used to reorder the arguments before dumping out a
Config.print_usage()
+def print_short_usage() -> None:
+ Config.print_short_usage()
+
+
def usage() -> str:
"""
Returns:
program usage help text as a string.
"""
return Config.usage()
+
+
+def short_usage() -> str:
+ """
+ Returns:
+ program short usage help text as a string.
+ """
+ return Config.short_usage()