#!/usr/bin/env python # -*- coding: utf-8 -*- # Copyright (C) 2010-2013 Bastian Kleineidam # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . """ patool [global-options] {extract|list|create|diff|search|formats} [sub-command-options] """ from __future__ import print_function import sys import argparse import pydoc import patoolib from patoolib.util import log_error, log_internal_error, PatoolError def run_extract(args): """Extract files from archive(s).""" res = 0 for archive in args.archive: try: patoolib.extract_archive(archive, verbosity=args.verbosity, outdir=args.outdir) except PatoolError as msg: log_error("error extracting %s: %s" % (archive, msg)) res += 1 return res def run_list(args): """List files in archive(s).""" res = 0 for archive in args.archive: try: # increase default verbosity since the listing output should be visible patoolib.list_archive(archive, verbosity=args.verbosity + 1) except PatoolError as msg: log_error("error listing %s: %s" % (archive, msg)) res += 1 return res def run_test(args): """Test files in archive(s).""" res = 0 for archive in args.archive: try: patoolib.test_archive(archive, verbosity=args.verbosity) except PatoolError as msg: log_error("error testing %s: %s" % (archive, msg)) res += 1 return res def run_create(args): """Create an archive from given files.""" res = 0 try: patoolib.create_archive(args.archive, args.filename, verbosity=args.verbosity) except PatoolError as msg: log_error("error creating %s: %s" % (args.archive, msg)) res = 1 return res def run_diff(args): """Show differences between two archives.""" try: res = patoolib.diff_archives(args.archive1, args.archive2, verbosity=args.verbosity) except PatoolError as msg: log_error("error showing differences between %s and %s: %s" % (args.archive1, args.archive2, msg)) res = 2 return res def run_search(args): """Search for pattern in given archive.""" try: res = patoolib.search_archive(args.pattern, args.archive, verbosity=args.verbosity) except PatoolError as msg: log_error("error searching %s: %s" % (args.archive, msg)) res = 2 return res def run_repack(args): """Repackage one archive in another format.""" res = 0 try: patoolib.repack_archive(args.archive_src, args.archive_dst, verbosity=args.verbosity) except PatoolError as msg: log_error("error repacking %s: %s" % (args.archive_src, msg)) res = 1 return res def run_formats (args): """List supported and available archive formats.""" patoolib.list_formats() return 0 class ArgumentParser(argparse.ArgumentParser): """Custom argument parser.""" def print_help(self, file=None): """Paginate help message on TTYs.""" msg = self.format_help() if file is None: file = sys.stdout if hasattr(file, "isatty") and file.isatty(): pydoc.pager(msg) else: print(msg, file=file) Examples = """\ EXAMPLES patool extract archive.zip otherarchive.rar patool --verbose test dist.tar.gz patool list package.deb patool --verbose create myfiles.zip file1.txt dir/ patool diff release1.0.tar.xz release2.0.zip patool search "def urlopen" python-3.3.tar.gz patool repack linux-2.6.33.tar.gz linux-2.6.33.tar.bz2 """ def create_argparser(): """Construct and return an argument parser.""" parser = ArgumentParser(description="A commandline archive handler.", epilog=Examples, formatter_class=argparse.RawDescriptionHelpFormatter) parser.add_argument('--verbose', '-v', action='count', default=0, dest='verbosity', help="verbose operation; can be given multiple times") subparsers = parser.add_subparsers(help='the archive command; type "patool COMMAND -h" for command-specific help', dest='command') # extract parser_extract = subparsers.add_parser('extract', help='extract one or more archives') parser_extract.add_argument('--outdir', help="output directory to extract to") parser_extract.add_argument('archive', nargs='+', help="an archive file") # list parser_list = subparsers.add_parser('list', help='list members or one or more archives') parser_list.add_argument('archive', nargs='+', help="an archive file") # create parser_create = subparsers.add_parser('create', help='create an archive') parser_create.add_argument('archive', help="the archive file; the file extension determines the archive program") parser_create.add_argument('filename', nargs='+', help="a file or directory to add to the archive; note that some archive programs do not support directories") # test parser_test = subparsers.add_parser('test', help='test an archive') parser_test.add_argument('archive', nargs='+', help='an archive file') # repack parser_repack = subparsers.add_parser('repack', help='repack an archive to a different format') parser_repack.add_argument('archive_src', help='source archive file') parser_repack.add_argument('archive_dst', help='target archive file') # diff parser_diff = subparsers.add_parser('diff', help='show differences between two archives') parser_diff.add_argument('archive1', help='the first archive file') parser_diff.add_argument('archive2', help='the second archive file') # search parser_search = subparsers.add_parser('search', help="search contents of archive members") parser_search.add_argument('pattern', help='the grep(1) compatible search pattern') parser_search.add_argument('archive', help='the archive file') # formats subparsers.add_parser('formats', help="show supported archive formats") # optional bash completion try: import argcomplete argcomplete.autocomplete(parser) except ImportError: pass return parser def main(): """Parse options and execute commands.""" try: argparser = create_argparser() args = argparser.parse_args() # run subcommand function return globals()["run_%s" % args.command](args) except KeyboardInterrupt: log_error("aborted") res = 1 except Exception: log_internal_error() res = 2 return res if __name__ == '__main__': sys.exit(main())