File Coverage

blib/lib/App/RegexFileUtils.pm
Criterion Covered Total %
statement 89 120 74.1
branch 39 62 62.9
condition 10 15 66.6
subroutine 8 8 100.0
pod 1 1 100.0
total 147 206 71.3


line stmt bran cond sub pod time code
1             package App::RegexFileUtils;
2              
3 8     8   1251453 use strict;
  8         20  
  8         217  
4 8     8   41 use warnings;
  8         19  
  8         184  
5 8     8   35 use File::Spec;
  8         14  
  8         155  
6 8     8   1634 use File::ShareDir::Dist qw( dist_share );
  8         4259  
  8         30  
7 8     8   2129 use File::Which qw( which );
  8         5361  
  8         7499  
8              
9             # ABSTRACT: use regexes with file utils like rm, cp, mv, ln
10             our $VERSION = '0.08'; # VERSION
11              
12              
13             sub main {
14 5     5 1 29308 my $class = shift;
15 5         13 my $mode = shift;
16 5         11 my $appname = $mode;
17 5         12 $mode =~ s!^.*/!!;
18 5         16 my @args = @_;
19            
20 5         11 my @options = ();
21 5         9 my $verbose = 0;
22 5         8 my $do_hidden = 0;
23 5         14 my $re;
24             my $sub;
25 5         0 my $modifiers;
26 5         14 my $modifiers_match = '';
27 5         9 my $tr;
28 5         8 my $static_dest = 0;
29            
30 5   66     43 while(defined($args[0]) && $args[0] =~ /^-/) {
31 1         2 my $arg = shift @args;
32            
33 1 50       5 if($arg =~ /^--recmd$/) {
    50          
    50          
34 0         0 $mode = shift @args;
35 0         0 $mode =~ s!^.*/!!;
36             } elsif($arg =~ /^--reverbose$/) {
37 0         0 $verbose = 1;
38             } elsif($arg =~ /^--reall$/) {
39 0         0 $do_hidden = 1;
40             } else {
41 1         5 push @options, $arg;
42             }
43             }
44            
45 5         12 my $dest = pop @args;
46            
47 5 50       25 unless(defined $dest) {
48 0         0 print STDERR "usage: $appname [options] [source files] /pattern/[substitution/]\n";
49 0         0 print STDERR " $appname [options] /pattern/ /path/to/destination\n";
50 0         0 print STDERR "\n";
51 0         0 print STDERR "--recmd [command] change the behavior of the tool\n";
52 0         0 print STDERR "--verbose print commands before they are executed\n";
53 0         0 print STDERR "--reall include hidden (so called `dot') files\n";
54 0         0 print STDERR "\n";
55 0         0 print STDERR "all other arguments are passed to the system tool\n";
56 0         0 exit;
57             }
58            
59 5         13 my $orig_mode = $mode;
60 5         17 $mode =~ s/^re//;
61            
62 5         62 my %modes = (
63             'mv' => 'mv',
64             'move' => 'mv',
65             'rename' => 'mv',
66             'cp' => 'cp',
67             'copy' => 'cp',
68             'ln' => 'ln',
69             'link' => 'ln',
70             'symlink' => 'ln',
71             'rm' => 'rm',
72             'remove' => 'rm',
73             'unlink' => 'rm',
74             'touch' => 'touch',
75             );
76            
77 5 50       16 unshift @options, '-s' if $mode eq 'symlink';
78            
79 5         12 $mode = $modes{$mode};
80 5 50       15 unless(defined $mode) {
81 0         0 print STDERR "unknown mode $orig_mode\n";
82 0         0 exit;
83             }
84            
85 5         8 my $no_dest = 0;
86 5 100 100     24 if($mode eq 'touch' || $mode eq 'rm') {
87 2         3 $no_dest = 1;
88             }
89            
90 5 100       61 if($dest =~ m!^(s|)/(.*)/(.*)/([ig]*)$!) {
    50          
    100          
    50          
91 2         6 $re = $2;
92 2         5 $sub = $3;
93 2         6 $modifiers = $4;
94 2 100       7 $modifiers_match = 'i' if $modifiers =~ /i/;
95            
96 2 50       6 if($no_dest) {
97 0         0 print STDERR "substitution `$mode' doesn't make sense\n";
98 0         0 exit;
99             }
100            
101             }
102            
103             elsif($dest =~ m!tr/(.*)/(.*)/$!) {
104 0         0 $tr = $1;
105 0         0 $sub = $2;
106            
107 0 0       0 if($no_dest) {
108 0         0 print STDERR "translation `$mode' doesn't make sense\n";
109             }
110             }
111            
112             elsif($dest =~ m!^(m|)/(.*)/([i]*)$!) {
113 2         6 $re = $2;
114 2         6 $modifiers = $3;
115 2         4 $modifiers_match = $3;
116             }
117            
118             elsif(-d $dest) {
119 1         2 my $src = pop @args;
120 1 50       11 if($src =~ m!^(m|)/(.*)/([i]*)$!) {
121 1         2 $static_dest = 1;
122 1         3 $re = $2;
123 1         2 $modifiers = $3;
124 1         3 $modifiers_match = $3;
125             } else {
126 0         0 die "source is not a regex";
127             }
128             }
129            
130             else {
131 0         0 die "destination is not a directory or a regex";
132             }
133            
134 5         11 my @files = @args;
135            
136 5 50       21 if(@files ==0) {
137 5 50       109 opendir(DIR, '.') || die "unable to opendir `.' $!";
138 5         91 @files = readdir(DIR);
139 5         48 closedir DIR;
140             }
141            
142 5         29 for(@files) {
143 35 100 66     396 next if /^\./ && !$do_hidden;
144 25 100 66     2385 next unless eval "/$re/$modifiers_match" || defined $tr;
145 14         65 my $old = $_;
146 14         26 my $new = $old;
147            
148 14         44 my @cmd = ($mode, @options, $old);
149            
150 14 50       80 if(defined $tr) {
    100          
    100          
151 0         0 eval "\$new =~ tr/$tr/$sub/";
152             } elsif(defined $sub) {
153 7         734 eval "\$new =~ s/$re/$sub/$modifiers";
154             } elsif($static_dest) {
155 2         4 $new = $dest;
156             } else {
157 5 50       9 if($no_dest) {
158 5         10 $new = '';
159             } else {
160 0         0 $new = '.';
161             }
162             }
163            
164 14 100       50 push @cmd, $new unless $no_dest;
165 14 50       49 print "% @cmd\n" if $verbose;
166            
167 14         74 __PACKAGE__->_fix_path(\@cmd);
168            
169 14         36076 system @cmd;
170              
171 14 50       10296 if ($? == -1) {
    50          
    100          
172 0         0 print STDERR "failed to execute: $!\n";
173 0         0 exit 2;
174             } elsif ($? & 127) {
175 0         0 print STDERR "child died with signal ", $? & 127, "\n";
176             } elsif($? >> 8) {
177 1         85 print "child exited with value ", $? >> 8, "\n";
178             }
179             }
180             }
181              
182 8         16 use constant _share_dir => do {
183 8         16 my $path;
184 8         30 $path = dist_share('App-RegexFileUtils');
185 8 50 33     970 die 'can not find share directory' unless $path && -d "$path/ppt";
186 8         1034 $path;
187 8     8   66 };
  8         17  
188              
189             sub _fix_path
190             {
191 14     14   53 my($class, $cmd) = @_;
192              
193 14 50       95 return unless $^O eq 'MSWin32';
194              
195 0 0         return if which($cmd->[0]);
196              
197 0           $cmd->[0] = File::Spec->catfile(
198             App::RegexFileUtils->_share_dir,
199             'ppt', $cmd->[0] . '.pl',
200             );
201 0           unshift @$cmd, $^X;
202             }
203              
204             1;
205              
206             __END__