#!/usr/bin/env python """ Archive extract script with sub-directory creation This tool is more or less same as atool """ # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 import os import re import sys import argparse import subprocess from subprocess import check_output from subprocess import call __author__ = 'lanxu ' def is_available(command): """Check if executable is available""" status, return_value = subprocess.getstatusoutput(command) if status < 127: return True return False def is_exe(fpath): """Check if file is executable""" return os.path.isfile(fpath) and os.access(fpath, os.X_OK) def run_command(command): """Run provided command and provide return value""" try: return_value = call(command) except (RuntimeError, TypeError, NameError, OSError) as error: print(error) raise return return_value def has_multiple_files(file): """Check if archive has multiple top level files""" file = re.escape(file) check_7z_command = "7z l -slt " + file + " | grep -c 'Path = [^/]*$'" check_tar_command = "tar --exclude=\"*/*\" -tf " + file + " | wc -l" check_command = None match = re.search(r"\.tar\.", file) if match != None: check_command = check_tar_command else: check_command = check_7z_command return_command = check_output(check_command, shell=True) if return_command is None: print('Something went horribly wrong') sys.exit(2) number_of_files = int(return_command.decode("utf-8")) if check_command is check_tar_command and number_of_files > 1: return True if check_command is check_7z_command and number_of_files >= 2: return True return False def extract(filename, loglevel): """ Main extract function for a single file """ extract_tools = [ { "extension": r"\.tar\.gz$", "command": "tar", "params": "-xf", "oparams": "-C", "dparams": "" }, { "extension": r"\.tar\.xz$", "command": "tar", "params": "-xf", "oparams": "-C", "dparams": "" }, { "extension": r"\.zip$", "command": "unzip", "params": "", "oparams": "-d", "dparams": "-qq -o" }, { "extension": r"\.rar$", "command": "unrar", "params": "x", "oparams": "", "dparams": "-inul -y -o" }, ] if loglevel == 'verbose': print("Processing file " + filename) for tool in extract_tools: match = re.search(tool["extension"], filename) if match is not None: if is_available(tool["command"]): command = [tool["command"]] if tool["params"] != "": command.append(tool["params"]) if tool["dparams"] != "" and loglevel != 'verbose': command.extend(tool["dparams"].split()) command.append(filename) output_path = "." if has_multiple_files(filename): base = os.path.basename(filename) basefile = os.path.splitext(base)[0] output_path = os.path.dirname(os.path.abspath(filename)) output_path = os.path.join(output_path, basefile) if loglevel == 'verbose': print("Extracting to " + output_path + "/") if not os.path.exists(output_path): os.makedirs(output_path) if tool["oparams"] != "": command.append(tool['oparams']) command.append(output_path) val = run_command(command) if val > 0: sys.exit(2) else: print("Command " + tool["command"] + " not found") sys.exit(2) def main(): """ Main function with argument parser """ loglevel = 'quiet' parser = argparse.ArgumentParser(description='Extract archives') parser.add_argument('input', nargs='+', help='input files') parser.add_argument('--verbose', dest='verbose', action='store_true', help='set verbose mode on', required=False, default=False) args = parser.parse_args() # Set verbosity if needed if args.verbose: loglevel = 'verbose' for filename in args.input: if os.path.isfile(filename) is False: print("No such file") sys.exit(2) else: extract(filename, loglevel) if __name__ == "__main__": # main(sys.argv[1:]) main()