File Coverage

bin/ptargrep
Criterion Covered Total %
statement 48 68 70.5
branch 12 32 37.5
condition 0 3 0.0
subroutine 11 12 91.6
pod n/a
total 71 115 61.7


line stmt bran cond sub pod time code
1             #!/usr/bin/perl
2             ##############################################################################
3             # Tool for using regular expressions against the contents of files in a tar
4             # archive. See 'ptargrep --help' for more documentation.
5             #
6              
7 1 50   1   3880 BEGIN { pop @INC if $INC[-1] eq '.' }
8 1     1   9 use strict;
  1         2  
  1         29  
9 1     1   12 use warnings;
  1         3  
  1         63  
10              
11 1     1   566 use Pod::Usage qw(pod2usage);
  1         85092  
  1         94  
12 1     1   806 use Getopt::Long qw(GetOptions);
  1         15950  
  1         6  
13 1     1   1094 use Archive::Tar qw();
  1         5  
  1         41  
14 1     1   8 use File::Path qw(mkpath);
  1         1  
  1         3077  
15              
16 1         181487 my(%opt, $pattern);
17              
18 1 50       8 if(!GetOptions(\%opt,
19             'basename|b',
20             'ignore-case|i',
21             'list-only|l',
22             'verbose|v',
23             'help|?',
24             )) {
25 0         0 pod2usage(-exitval => 1, -verbose => 0);
26             }
27              
28              
29 1 50       978 pod2usage(-exitstatus => 0, -verbose => 2) if $opt{help};
30              
31 1 50       5 pod2usage(-exitval => 1, -verbose => 0,
32             -message => "No pattern specified",
33             ) unless @ARGV;
34 1         5 make_pattern( shift(@ARGV) );
35              
36 1 50       4 pod2usage(-exitval => 1, -verbose => 0,
37             -message => "No tar files specified",
38             ) unless @ARGV;
39              
40 1         6 process_archive($_) foreach @ARGV;
41              
42 1         0 exit 0;
43              
44              
45             sub make_pattern {
46 1     1   3 my($pat) = @_;
47              
48 1 50       4 if($opt{'ignore-case'}) {
49 0         0 $pattern = qr{(?im)$pat};
50             }
51             else {
52 1         11 $pattern = qr{(?m)$pat};
53             }
54             }
55              
56              
57             sub process_archive {
58 1     1   3 my($filename) = @_;
59              
60 1         6 _log("Processing archive: $filename");
61 1         11 my $next = Archive::Tar->iter($filename);
62 1         3 while( my $f = $next->() ) {
63 1 50       2 next unless $f->is_file;
64 1 50       2 match_file($f) if $f->size > 0;
65             }
66             }
67              
68              
69             sub match_file {
70 1     1   3 my($f) = @_;
71 1         2 my $path = $f->name;
72 1         4 my $prefix = $f->prefix;
73 1 50       8 if (defined $prefix) {
74 1         31 $path = File::Spec->catfile($prefix, $path);
75             }
76              
77 1         4 _log("filename: %s (%d bytes)", $path, $f->size);
78              
79 1         3 my $body = $f->get_content();
80 1 50       7 if($body !~ $pattern) {
81 0         0 _log(" no match");
82 0         0 return;
83             }
84              
85 1 50       3 if($opt{'list-only'}) {
86 1         9 print $path, "\n";
87 1         10 return;
88             }
89              
90 0         0 save_file($path, $body);
91             }
92              
93              
94             sub save_file {
95 0     0   0 my($path, $body) = @_;
96              
97 0         0 _log(" found match - extracting");
98 0         0 my($fh);
99 0         0 my($dir, $file) = $path =~ m{\A(?:(.*)/)?([^/]+)\z};
100 0 0 0     0 if($dir and not $opt{basename}) {
101 0         0 _log(" writing to $dir/$file");
102 0         0 $dir =~ s{\A/}{./};
103 0 0       0 mkpath($dir) unless -d $dir;
104 0 0       0 open $fh, '>', "$dir/$file" or die "open($dir/$file): $!";
105             }
106             else {
107 0         0 _log(" writing to ./$file");
108 0 0       0 open $fh, '>', $file or die "open($file): $!";
109             }
110 0         0 print $fh $body;
111 0         0 close($fh);
112             }
113              
114              
115             sub _log {
116 2 50   2   6 return unless $opt{verbose};
117 0           my($format, @args) = @_;
118 0           warn sprintf($format, @args) . "\n";
119             }
120              
121              
122             __END__