File Coverage

blib/lib/File/Irenamer.pm
Criterion Covered Total %
statement 15 90 16.6
branch 0 42 0.0
condition 0 7 0.0
subroutine 5 11 45.4
pod 0 6 0.0
total 20 156 12.8


line stmt bran cond sub pod time code
1             package File::Irenamer;
2             ##############################################################################
3             # $Id: Irenamer.pm,v 1.3 2004/11/07 13:59:23 bheckel Exp bheckel $
4             #
5             # $Log: Irenamer.pm,v $
6             # Revision 1.3 2004/11/07 13:59:23 bheckel
7             # Adjust docs
8             #
9             # Revision 1.2 2004/11/07 02:30:36 bheckel
10             # Cleaned up release for initial upload to CPAN
11             #
12             # Revision 1.1 2004/11/07 02:29:39 bheckel
13             # Initial revision
14             #
15             ##############################################################################
16 1     1   53983 use 5.008002;
  1         4  
  1         33  
17 1     1   5 use strict;
  1         2  
  1         31  
18 1     1   4 use warnings;
  1         5  
  1         33  
19 1     1   2352 use Getopt::Std;
  1         89  
  1         62  
20 1     1   6 use File::Find;
  1         1  
  1         1269  
21              
22             require Exporter;
23              
24             our @ISA = qw(Exporter);
25             our %EXPORT_TAGS = ( 'all' => [ qw(
26             ) ] );
27             our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
28             our @EXPORT = qw(
29             InteractiveRename
30             );
31             our $VERSION = sprintf("%d.%02d", q$Revision: 1.3 $ =~ /(\d+)\.(\d+)/o);
32             our %opts;
33              
34             getopts('drv', \%opts);
35              
36              
37             # Main
38             sub InteractiveRename {
39 0     0 0   my (@options) = @_;
40              
41 0 0         $opts{d} = 1 if grep { /debug/ } @options;
  0            
42 0 0         $opts{r} = 1 if grep { /recurse/ } @options;
  0            
43 0 0         $opts{v} = 1 if grep { /verbose/ } @options;
  0            
44              
45 0 0         if ( $ARGV[0] ) {
46             # Remove user's trailing slash if necessary.
47 0           $ARGV[0] =~ s#/$##;
48             } else {
49             # Default to current working dir.
50 0           $ARGV[0] = '.';
51             }
52              
53 0 0         print "DEBUG \$ARGV[0] is $ARGV[0]\n" if $opts{d};
54              
55 0           RenameFiles(ParseChanges(EditFilesInEditor(ReadFiles($ARGV[0]))));
56              
57 0           exit 0;
58             }
59              
60              
61             my @FILES;
62             sub Wanted {
63 0 0   0 0   -f $_ and push @FILES, $File::Find::name;
64             }
65              
66              
67             sub ReadFiles {
68 0     0 0   my $dir = shift;
69              
70 0           @FILES = ();
71              
72 0 0         die "ERROR: no input directory in ReadFiles(). Exiting.\n" if ! $dir;
73              
74 0 0         if ( $opts{r} ) {
75 0           find \&Wanted, $dir;
76             } else {
77 0 0         opendir DH, "$dir" or die "Error: $0: $!";
78 0   0       @FILES = grep { !/^..?$/ && !-d } map "$dir/$_", readdir DH;
  0            
79 0           close DH;
80             }
81              
82 0           return @FILES;
83             }
84              
85              
86             sub EditFilesInEditor {
87 0     0 0   my @orignames = @_;
88              
89 0           my $rand = int(rand(42)) + time + $$;
90 0           my $tmpfile = "$ENV{TMP}/renamer-pl.$rand.tmp";
91 0   0       open TMPF, ">$tmpfile" || die "Can't create $tmpfile in $ENV{TMP}: $!\n";
92              
93 0           print TMPF <<"EOT";
94             #
95             # Changes to these filenames will be made after exiting this
96             # tempfile. Delete all lines to cancel.
97             #
98             EOT
99              
100 0           for ( @orignames ) {
101 0           print TMPF "$_\n";
102             }
103            
104 0           close TMPF;
105              
106 0           system "$ENV{EDITOR} $tmpfile";
107              
108             # We make changes to $tmpfile within our favorite editor...Vim, right? ;-)
109              
110 0   0       open TMPF, "<$tmpfile" || die "Can't open $tmpfile : $!\n";
111 0           my @newnames = ;
112 0           @newnames = grep { !/^#/ } @newnames;
  0            
113              
114 0 0         if ( $opts{d} ) {
115 0           close TMPF;
116 0           print "DEBUG: $tmpfile\n";
117             } else {
118             # TODO only if user does not cancel
119 0 0         close TMPF && unlink $tmpfile;
120             }
121              
122 0           return \@orignames, \@newnames;
123             }
124              
125              
126             # Parse saved editor diffs into a hash.
127             sub ParseChanges {
128 0     0 0   my $origarrref = shift;
129 0           my $newarrref = shift;
130              
131 0 0         if ( scalar @$origarrref != scalar @$newarrref ) {
132 0           die "ERROR: Problem with parsing filename change file.\nDifferent " .
133             "number of files in old vs. new. Exiting.\n";
134             }
135              
136 0           my %same = map { $_, 1 } @$origarrref;
  0            
137              
138 0           my %torename;
139 0           my $i = 0;
140 0           foreach my $f ( @$newarrref ) {
141 0           chomp $f; # take away newlines used previously for easier editing
142 0 0         if ( ! $same{$f} ) {
143 0           $torename{@$origarrref[$i]} = @$newarrref[$i];
144             }
145 0           $i++;
146             }
147              
148 0           return \%torename;
149             }
150              
151              
152             sub RenameFiles {
153 0     0 0   my $hr = shift;
154              
155 0 0         if ( ! keys %$hr ) {
156 0 0         die "No changes requested. Exiting.\n" if $opts{v};
157             } else {
158 0 0         print "We are about to rename:\n" if $opts{v};
159             }
160              
161 0           foreach ( sort keys %$hr ) {
162 0 0         print " FROM:\t$_\n TO:\t$$hr{$_}\n\n" if $opts{v};
163             }
164              
165 0 0         if ( $opts{v} ) {
166 0           print "Proceed? [yes/no] ";
167 0 0         if ( !~ /yes/i ) {
168 0           die "cancelled\n";
169             }
170             }
171              
172             # It's possible to try to rename a file into a subdir that doesn't exist,
173             # etc. Can't stop all stupidity but can at least whine about it.
174 0           my $rc = 1;
175 0           foreach ( sort keys %$hr ) {
176 0           $rc = rename $_, $$hr{$_};
177 0 0         print "Potential error during rename of $_\n" if $rc ne 1;
178             }
179              
180 0 0         if ( $opts{v} ) {
181 0           print "Directory contents after committed changes:\n";
182 0           map { print " $_\n" } ReadFiles($ARGV[0]);
  0            
183             }
184              
185 0           return 0;
186             }
187              
188              
189             1;
190              
191              
192             __END__