#!/usr/local/bin/perl use File::Basename; use File::Copy; use File::Spec; use File::Find; use Getopt::Std; #use Backfire; use Cwd qw(realpath); my %opt; getopts("Fva:b:d:", \%opt ); for my $o (qw(a b d)) { unless (defined($opt{$o})) { usage(); exit(2); } } my $mvargs = ($^O eq 'freebsd') ? '-n' : '-i'; my $debug; my %mkdhash; my $act = $opt{a}; my $dest = realpath($opt{d}); my @destsplit = File::Spec->splitdir($dest); my $base = realpath($opt{b}); my @basesplit = File::Spec->splitdir(realpath($opt{b})); $debug = 1 if defined($opt{v}); unless (chdir($dest)) { fail("Can't chdir to $dest: $!"); exit(1); } while (my $F = ) { chomp($F); $F =~ s/\/+/\//g; $F = File::Spec->canonpath($F); unless (index($F,'/') == 0) { $F = File::Spec->catfile(@basesplit,$F); } $F = File::Spec->canonpath($F); # Again! :-) print "Item: $F\n" if ($debug); if (!-e $F) { fail("$F does not exist."); } elsif (-d $F) { grabwholedir($F); } elsif (-f $F) { do_it($F); } else { fail("$F: Not a file/dir/symlink."); } } sub do_it { my $currfile = shift; my @cfsplit = File::Spec->splitdir($currfile); shift @cfsplit for (0 .. $#basesplit); my $outfile = File::Spec->catfile(@destsplit,@cfsplit); my $mkdh = dirname($outfile); print "Creating: $mkdh\n" if ( ($debug) && (! -d $mkdh) ); mkdirhier($mkdh); if (-e $outfile) { print "$outfile already exists\n"; if (!defined $opt{F}) { return; } else { unlink($outfile); } } print "[$currfile] -> [$outfile]\n" if ($debug); if ($act eq 'copy') { my $stat = File::Copy::syscopy($currfile,$outfile); fail("copy: $currfile to $outfile: $!") unless $stat; } elsif (($act eq 'rename')||($act eq 'move')) { my $stat = system("/bin/mv",$mvargs,$currfile,$outfile); if ($?) { fail("Rename failed ($?): $!\n"); } } elsif ($act eq 'stat') { fail("stat: $currfile not found.") unless (-e $currfile); } else { fail("'$act' is not a valid action."); exit(2); } } sub fail { my $str = shift; print STDERR $str . "\n"; } sub grabwholedir { my $s = shift; my @files; find({ wanted => sub { push (@files,$File::Find::name) }, follow => 1}, $s); foreach my $G (@files) { if (-d $G) { mkdirhier($G); } else { do_it($G); } } } sub mkdirhier { my $md = shift; my @d = File::Spec->splitdir($md); shift @d for (0 .. $#destsplit); # basesplit for my $i (0 .. $#d) { next if ($d[$i] =~ /^\.{1,2}$/); my $newdir = File::Spec->catdir(@d[0 .. $i]); unless ($mkdhash{$newdir}) { if (-e $newdir) { $mkdhash{$newdir} = 1; next; } mkdir($newdir) or fail("mkdir: $newdir: $!"); print "$newdir created\n" if ($debug); } $mkdhash{$newdir} = 1; } } sub usage { print <