From a2d6e4f95ac867bddadd5925b88eae0206225c98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C5=82awek=20Ehlert?= Date: Wed, 17 May 2017 11:09:08 +0200 Subject: [PATCH] Add --force-basename option When extracting multiple similar archives with only one top-level element, user usually wants to have them in a destination directory named after archive's name. Currently the first archive is extracted to a directory named after the single top-level element while other archives are extracted to directories named after archive's basename. The `--force-basename` option is forcing the latter behaviour for every archive. For example, let's say we have two archives, with only one top-level directory in them (called `var`): ``` $ ls BundleLogs*zip BundleLogs-1495008842230.zip BundleLogs-1495008843374.zip ``` When trying to unpack them at once: ``` $ unp --output /tmp/logs BundleLogs*zip ``` The default behaviour leaves us with: ``` $ ls /tmp/logs BundleLogs-1495008843374 var ``` Using `--force-basename` option: ``` $ unp --force-basename --output /tmp/logs_basename BundleLogs*zip ``` We get the following result: ``` $ ls /tmp/logs_basename BundleLogs-1495008842230 BundleLogs-1495008843374 ``` --- unp.py | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/unp.py b/unp.py index 4e287cc..d30f675 100644 --- a/unp.py +++ b/unp.py @@ -83,9 +83,10 @@ class UnpackerBase(object): args = () cwd = OUTPUT_FOLDER - def __init__(self, filename, silent=False): + def __init__(self, filename, silent=False, force_basename=False): self.filename = filename self.silent = silent + self.force_basename = force_basename self.assert_available() @classmethod @@ -164,8 +165,9 @@ def finish_unpacking(self, tmp_dir, dst): # Find how many unpacked files there are. If there is more than # one, then we have to go to the fallback destination. Same goes # if the intended destination already exists. + # This behaviour can also be forced with `force_basename` attribute. contents = os.listdir(tmp_dir) - if len(contents) == 1: + if len(contents) == 1 and not self.force_basename: the_one_file = contents[0] intended_dst = os.path.join(dst, the_one_file) else: @@ -530,8 +532,14 @@ def select_unpacker(ctx, param, value): 'debugging broken archives usually. Note that this command ' 'when executed directly might spam your current working ' 'directory!') +@click.option('--force-basename', is_flag=True, default=False, + help='Force unpacking to a directory with name ' + 'derived from archive\'s basename. ' + 'Useful when extracting many similar archives ' + 'with only one top-level element.' + ) @click.version_option() -def cli(files, silent, output, dump_command, forced_unpacker): +def cli(files, silent, output, dump_command, forced_unpacker, force_basename): """unp is a super simple command line application that can unpack a lot of different archives. No matter if you unpack a zip or tarball, the syntax for doing it is the same. Unp will also automatically ensure @@ -556,7 +564,9 @@ def cli(files, silent, output, dump_command, forced_unpacker): unpacker_cls = forced_unpacker else: unpacker_cls = get_unpacker_class(filename) - unpackers.append(unpacker_cls(filename, silent=silent)) + unpackers.append( + unpacker_cls(filename, silent=silent, force_basename=force_basename) + ) for unpacker in unpackers: if dump_command: