Add search command.

This commit is contained in:
Bastian Kleineidam 2013-02-22 18:38:52 +01:00
parent 7d0d0f9601
commit c854102908
6 changed files with 141 additions and 55 deletions

View File

@ -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

View File

@ -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

View File

@ -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
View File

@ -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."""

View File

@ -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)

31
tests/test_search.py Normal file
View File

@ -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)