Add search command.
This commit is contained in:
parent
7d0d0f9601
commit
c854102908
|
@ -1,3 +1,10 @@
|
|||
1.0 "" (released xx.xx.2013)
|
||||
|
||||
* Add support for grepping in archive contents.
|
||||
* Fixed Python lzma archive handling.
|
||||
* Fixed lzop and lrzip archive handling.
|
||||
|
||||
|
||||
0.19 "The Kids Are All Right" (released 21.2.2013)
|
||||
|
||||
* Support the lzma module in Python >= 3.3
|
||||
|
|
57
doc/patool.1
57
doc/patool.1
|
@ -1,5 +1,5 @@
|
|||
.\" -*- nroff -*-
|
||||
.\" Copyright (C) 2010-2012 Bastian Kleineidam
|
||||
.\" 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
|
||||
|
@ -11,15 +11,16 @@
|
|||
.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
.\" GNU General Public License for more details.
|
||||
.\"
|
||||
.TH PATOOL "1" "February 2010" "patool"
|
||||
.TH PATOOL "1" "February 2013" "patool"
|
||||
.SH NAME
|
||||
patool - portable command line archive file manager
|
||||
.SH SYNOPSIS
|
||||
\fBpatool\fP (\fBlist\fP|\fBtest\fP) [\fB\-\-verbose\fP] <\fIarchive-file\fP>...
|
||||
\fBpatool\fP \fBextract\fP [\fB\-\-verbose\fP] [\fB\-\-outdir=\fP\fIDIRNAME\fP] <\fIarchive-file\fP>...
|
||||
\fBpatool\fP \fBcreate\fP [\fB\-\-verbose\fP] <\fIarchive-file\fP> [\fIfiles\fP...]
|
||||
\fBpatool\fP \fBdiff\fP <\fIarchive1\fP> <\fIarchive2\fP>
|
||||
\fBpatool\fP \fBrepack\fP <\fIarchive1\fP> <\fIarchive2\fP>
|
||||
\fBpatool\fP \fBdiff\fP [\fB\-\-verbose\fP] <\fIarchive1\fP> <\fIarchive2\fP>
|
||||
\fBpatool\fP \fBsearch\fP [\fB\-\-verbose\fP] <\fIpattern\fP> <\fIarchive-file\fP>...
|
||||
\fBpatool\fP \fBrepack\fP [\fB\-\-verbose\fP] <\fIarchive1\fP> <\fIarchive2\fP>
|
||||
\fBpatool\fP \fBformats\fP
|
||||
.SH DESCRIPTION
|
||||
Various archive types can be created, extracted, tested and listed by
|
||||
|
@ -47,10 +48,20 @@ installed.
|
|||
\fBpatool list package.deb\fP
|
||||
\fPpatool create --verbose myfiles.zip file1.txt dir/\fP
|
||||
\fBpatool diff release1.0.tar.gz release2.0.zip\fP
|
||||
\fBpatool search "def urlopen" python-3.3.tar.gz\fP
|
||||
\fBpatool repack linux-2.6.33.tar.gz linux-2.6.33.tar.bz2\fP
|
||||
.SH COMMANDS
|
||||
Several commands and options are available.
|
||||
.SS \fBextract\fP
|
||||
The following rules apply to all commands:
|
||||
.IP "\(bu" 4
|
||||
Existing files are never overwritten.
|
||||
.IP "\(bu" 4
|
||||
The original archive will never be removed.
|
||||
.IP "\(bu" 4
|
||||
Verbose operation displays more info about what patool does. It also
|
||||
displays more info from the helper application if it's supported.
|
||||
.PP
|
||||
Several commands are available.
|
||||
.SS extract
|
||||
Extract files from an archive. The original archive will never
|
||||
be removed and is left as it is.
|
||||
.br
|
||||
|
@ -68,35 +79,27 @@ of files from the extracted archive.
|
|||
.PP
|
||||
All extracted files are ensured that they are readable by the
|
||||
current user.
|
||||
.TP
|
||||
\fB\-v\fP, \fB\-\-verbose\fP
|
||||
Be verbose when extracting (if the helper application supports it).
|
||||
.SS \fBlist\fP
|
||||
.SS list
|
||||
List files in an archive.
|
||||
.TP
|
||||
\fB\-v\fP, \fB\-\-verbose\fP
|
||||
Verbose archive listing (if the helper application supports it).
|
||||
.SS \fBcreate\fP
|
||||
.SS create
|
||||
Create an archive from given files. At least on of the given files to add
|
||||
to the archive has to exist (non-existing files are ignored).
|
||||
The format of the archive to create is determined by the archive file
|
||||
extension.
|
||||
.TP
|
||||
\fB\-v\fP, \fB\-\-verbose\fP
|
||||
Verbose operation (if the helper application supports it).
|
||||
.SS \fBtest\fP
|
||||
.SS test
|
||||
Test files in an archive. If the helper application does not support
|
||||
testing, the archive contents are listed instead.
|
||||
.TP
|
||||
\fB\-v\fP, \fB\-\-verbose\fP
|
||||
Verbose archive testing (if the helper application supports it).
|
||||
.SS \fBdiff\fP
|
||||
Show differences between two archives with the \fBdiff(1)\fP utility.
|
||||
.SS diff
|
||||
Show differences between two archives with the \fBdiff(1)\fP program.
|
||||
The diff options used are \fB\-urN\fP.
|
||||
.SS \fBrepack\fP
|
||||
.SS search
|
||||
Search in archive contents for given pattern using the \fBgrep(1)\fP program.
|
||||
The grep options used are \fB\-r\fP; additional options can be supplied
|
||||
with the \fBGREP_OPTIONS\fP environment variable.
|
||||
.SS repack
|
||||
Repackage archive to a different format. The target archive format is
|
||||
determined by the file extension.
|
||||
.SS \fBformats\fP
|
||||
.SS formats
|
||||
Show all supported archive formats (ie. which helper applications
|
||||
are available).
|
||||
.SH HELP OPTION
|
||||
|
@ -107,6 +110,6 @@ For example:
|
|||
\fBpatool \-\-help\fP - display help for patool
|
||||
\fBpatool extract \-\-help\fP - display help for the extract command
|
||||
.SH AUTHOR
|
||||
Bastian Kleineidam <calvin@users.sourceforge.net>
|
||||
Bastian Kleineidam <bastian.kleineidam@web.de>
|
||||
.SH COPYRIGHT
|
||||
Copyright \(co 2010-2012 Bastian Kleineidam
|
||||
Copyright \(co 2010-2013 Bastian Kleineidam
|
||||
|
|
|
@ -10,8 +10,9 @@ SYNOPSIS
|
|||
patool extract [--verbose] [--outdir=DIRNAME] <archive-
|
||||
file>...
|
||||
patool create [--verbose] <archive-file> [files...]
|
||||
patool diff <archive1> <archive2>
|
||||
patool repack <archive1> <archive2>
|
||||
patool diff [--verbose] <archive1> <archive2>
|
||||
patool search [--verbose] <pattern> <archive-file>...
|
||||
patool repack [--verbose] <archive1> <archive2>
|
||||
patool formats
|
||||
|
||||
DESCRIPTION
|
||||
|
@ -42,10 +43,21 @@ EXAMPLES
|
|||
patool list package.deb
|
||||
patool create --verbose myfiles.zip file1.txt dir/
|
||||
patool diff release1.0.tar.gz 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
|
||||
|
||||
COMMANDS
|
||||
Several commands and options are available.
|
||||
The following rules apply to all commands:
|
||||
|
||||
· Existing files are never overwritten.
|
||||
|
||||
· The original archive will never be removed.
|
||||
|
||||
· Verbose operation displays more info about what patool
|
||||
does. It also displays more info from the helper applica‐
|
||||
tion if it's supported.
|
||||
|
||||
Several commands are available.
|
||||
|
||||
extract
|
||||
Extract files from an archive. The original archive will never
|
||||
|
@ -63,39 +75,28 @@ COMMANDS
|
|||
All extracted files are ensured that they are readable by the
|
||||
current user.
|
||||
|
||||
-v, --verbose
|
||||
Be verbose when extracting (if the helper application
|
||||
supports it).
|
||||
|
||||
list
|
||||
List files in an archive.
|
||||
|
||||
-v, --verbose
|
||||
Verbose archive listing (if the helper application sup‐
|
||||
ports it).
|
||||
|
||||
create
|
||||
Create an archive from given files. At least on of the given
|
||||
files to add to the archive has to exist (non-existing files
|
||||
are ignored). The format of the archive to create is deter‐
|
||||
mined by the archive file extension.
|
||||
|
||||
-v, --verbose
|
||||
Verbose operation (if the helper application supports
|
||||
it).
|
||||
|
||||
test
|
||||
Test files in an archive. If the helper application does not
|
||||
Test files in an archive. If the helper application does not
|
||||
support testing, the archive contents are listed instead.
|
||||
|
||||
-v, --verbose
|
||||
Verbose archive testing (if the helper application sup‐
|
||||
ports it).
|
||||
|
||||
diff
|
||||
Show differences between two archives with the diff(1) utility.
|
||||
Show differences between two archives with the diff(1) program.
|
||||
The diff options used are -urN.
|
||||
|
||||
search
|
||||
Search in archive contents for given pattern using the grep(1)
|
||||
program. The grep options used are -r; additional options can
|
||||
be supplied with the GREP_OPTIONS environment variable.
|
||||
|
||||
repack
|
||||
Repackage archive to a different format. The target archive
|
||||
format is determined by the file extension.
|
||||
|
@ -112,11 +113,11 @@ HELP OPTION
|
|||
patool extract --help - display help for the extract command
|
||||
|
||||
AUTHOR
|
||||
Bastian Kleineidam <calvin@users.sourceforge.net>
|
||||
Bastian Kleineidam <bastian.kleineidam@web.de>
|
||||
|
||||
COPYRIGHT
|
||||
Copyright © 2010-2012 Bastian Kleineidam
|
||||
Copyright © 2010-2013 Bastian Kleineidam
|
||||
|
||||
|
||||
|
||||
patool February 2010 PATOOL(1)
|
||||
patool February 2013 PATOOL(1)
|
||||
|
|
12
patool
12
patool
|
@ -1,6 +1,6 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (C) 2010-2012 Bastian Kleineidam
|
||||
# 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
|
||||
|
@ -70,8 +70,7 @@ def test (archive, *archives, **kwargs):
|
|||
@baker.command(shortopts=shortopts, params=params)
|
||||
def create (archive, file1, *files, **kwargs):
|
||||
"""Create an archive from given files."""
|
||||
allfiles = (file1,)+files
|
||||
return handle_archive(archive, 'create', *allfiles, **kwargs)
|
||||
return handle_archive(archive, 'create', file1, *files, **kwargs)
|
||||
|
||||
|
||||
@baker.command(shortopts=shortopts, params=params)
|
||||
|
@ -81,6 +80,13 @@ def diff (archive1, archive2, **kwargs):
|
|||
return diff(archive1, archive2, **kwargs)
|
||||
|
||||
|
||||
@baker.command(shortopts=shortopts, params=params)
|
||||
def search(pattern, archive1, *archives, **kwargs):
|
||||
"""Search for pattern in all given archives."""
|
||||
from patoolib import search
|
||||
return search(pattern, archive1, *archives, **kwargs)
|
||||
|
||||
|
||||
@baker.command(shortopts=shortopts, params=params)
|
||||
def repack (archive1, archive2, **kwargs):
|
||||
"""Repackage one archive in another format."""
|
||||
|
|
|
@ -473,6 +473,12 @@ def check_archive_arguments (archive, command, *args):
|
|||
if not args:
|
||||
raise util.PatoolError("missing second archive filename for diff")
|
||||
util.check_existing_filename(args[0])
|
||||
elif command == 'search':
|
||||
if not archive:
|
||||
# archive is the search pattern
|
||||
raise util.PatoolError("empty search pattern")
|
||||
for arg in args:
|
||||
util.check_existing_filename(arg)
|
||||
else:
|
||||
util.check_existing_filename(archive)
|
||||
|
||||
|
@ -563,7 +569,6 @@ def _diff_archives (archive1, archive2, **kwargs):
|
|||
return 0
|
||||
diff = util.find_program("diff")
|
||||
if not diff:
|
||||
# XXX more helpful error message
|
||||
msg = "The diff(1) program is required for showing archive differences, please install it."
|
||||
raise util.PatoolError(msg)
|
||||
tmpdir1 = util.tmpdir()
|
||||
|
@ -579,6 +584,32 @@ def _diff_archives (archive1, archive2, **kwargs):
|
|||
shutil.rmtree(tmpdir1, onerror=rmtree_log_error)
|
||||
|
||||
|
||||
def _search_archives(pattern, *archives, **kwargs):
|
||||
"""Search for given pattern in all archives."""
|
||||
grep = util.find_program("grep")
|
||||
if not grep:
|
||||
msg = "The grep(1) program is required for searching archive contents, please install it."
|
||||
raise util.PatoolError(msg)
|
||||
errors = 0
|
||||
for archive in archives:
|
||||
try:
|
||||
errors += _search_archive(grep, pattern, archive, **kwargs)
|
||||
except util.PatoolError as msg:
|
||||
util.log_error("grep error: %s" % msg)
|
||||
errors += 1
|
||||
return errors
|
||||
|
||||
|
||||
def _search_archive(grep, pattern, archive, **kwargs):
|
||||
"""Extract one archive and search for given pattern in extracted files."""
|
||||
tmpdir = util.tmpdir()
|
||||
try:
|
||||
_handle_archive(archive, 'extract', outdir=tmpdir, **kwargs)
|
||||
return util.run([grep, "-r", "-e", pattern, "."], cwd=tmpdir)
|
||||
finally:
|
||||
shutil.rmtree(tmpdir, onerror=rmtree_log_error)
|
||||
|
||||
|
||||
def _repack_archive (archive1, archive2, **kwargs):
|
||||
"""Repackage an archive to a different format."""
|
||||
format1, compression1 = get_archive_format(archive1)
|
||||
|
@ -619,6 +650,8 @@ def handle_archive (archive, command, *args, **kwargs):
|
|||
try:
|
||||
if command == "diff":
|
||||
res = _diff_archives(archive, args[0], **kwargs)
|
||||
elif command == "search":
|
||||
res = _search_archives(archive, *args, **kwargs)
|
||||
elif command == "repack":
|
||||
res = _repack_archive(archive, args[0], **kwargs)
|
||||
else:
|
||||
|
@ -663,6 +696,11 @@ def diff (archive1, archive2, verbose=False):
|
|||
return handle_archive(archive1, 'diff', archive2, verbose=verbose)
|
||||
|
||||
|
||||
def search(pattern, *archives, **kwargs):
|
||||
"""Search pattern in archive members."""
|
||||
return handle_archive(pattern, 'search', *archives, **kwargs)
|
||||
|
||||
|
||||
def repack (archive1, archive2, verbose=False):
|
||||
"""Repack archive to different file and/or format."""
|
||||
return handle_archive(archive1, 'repack', archive2, verbose=verbose)
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (C) 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 <http://www.gnu.org/licenses/>.
|
||||
import unittest
|
||||
import os
|
||||
import patoolib
|
||||
from . import datadir, needs_program
|
||||
|
||||
class ArchiveSearchTest (unittest.TestCase):
|
||||
|
||||
@needs_program('grep')
|
||||
@needs_program('unzip')
|
||||
@needs_program('tar')
|
||||
def test_search(self):
|
||||
pattern = "42"
|
||||
archive1 = os.path.join(datadir, "t.tar")
|
||||
archive2 = os.path.join(datadir, "t.zip")
|
||||
res = patoolib.handle_archive(pattern, "search", archive1, archive2)
|
||||
self.assertEqual(res, 0)
|
Loading…
Reference in New Issue