#!/usr/bin/perl use warnings; use strict; use Getopt::Long; use File::Copy qw(move); use File::Temp qw(tempdir); use File::Basename qw(basename); use File::Spec::Functions qw(catdir no_upwards rootdir); use constant BASEDIR => do { require Cwd; Cwd::cwd() }; sub slurp_dir { my $dir = shift; opendir my ($dh), $dir or die "Couldn't read directory $dir: $!\n"; readdir $dh; } sub run_cmd { print "\t@_\n"; my $exit = system(@_); require POSIX; if (POSIX::WIFEXITED($exit)) { return 1 if POSIX::WEXITSTATUS($exit) == 0; print "\tReturned non-zero exit status\n"; return; } else { print "\tQuitting: Subprocess exited abnormally\n"; exit 1; } } sub mangle_targetdir { my ($exdir) = @_; my $basedir_rx = join '.?', map quotemeta, split /[-_ ]/, $exdir; my ($tarbase, @morefiles) = no_upwards(slurp_dir $exdir); my $exdir_tar = catdir($exdir, $tarbase); if (@morefiles or ! -d $exdir_tar or $tarbase !~ /\A$basedir_rx/i) { print "\tExtracted in $exdir\n"; return; } print "\tExtracted in $tarbase\n" if $tarbase ne $exdir; my $tempdir = tempdir(DIR => BASEDIR); my $tempdir_tar = catdir($tempdir, $tarbase); my $basedir_tar = catdir(BASEDIR, $tarbase); move $exdir_tar, $tempdir_tar and rmdir $exdir and move $tempdir_tar, $basedir_tar and rmdir $tempdir or print "\tFailed moving $exdir_tar to $basedir_tar: $!\n"; } sub run_in_dir { my $basename = basename shift; mkdir $basename; run_cmd(@_); mangle_targetdir($basename); } GetOptions( 'list|l!' => \(my $list = ''), 'overwrite|o!' => \(my $overwrite = ''), 'remove|r!' => \(my $remove = ''), ) and @ARGV or die "usage: FIXME\n"; # FIXME my %ext = $list ? ( zip => sub { local %_ = @_; unzip => -l => $_{archive} }, tar => sub { local %_ = @_; tar => tv => -f => $_{archive}, }, tgz => sub { local %_ = @_; tar => tv => '--gzip', -f => $_{archive}, }, tbz2 => sub { local %_ = @_; tar => tv => '--bzip2', -f => $_{archive}, }, tarz => sub { local %_ = @_; tar => tv => '--compress', -f => $_{archive}, }, ) : ( zip => sub { local %_ = @_; unzip => -q => -d => $_{dir}, $_{archive} }, tar => sub { local %_ = @_; tar => x => -f => $_{archive}, -C => $_{dir}, }, tgz => sub { local %_ = @_; tar => x => '--gzip', -f => $_{archive}, -C => $_{dir}, }, tbz2 => sub { local %_ = @_; tar => x => '--bzip2', -f => $_{archive}, -C => $_{dir}, }, tarz => sub { local %_ = @_; tar => x => '--compress', -f => $_{archive}, }, ); @ext{qw(tar.gz tar.bz2 tar.z tar.Z)} = @ext{qw(tgz tbz2 tarz tarz)}; my $rx = join '|', map quotemeta, keys %ext; $rx = qr/\A (.*) \. ($rx) \z/ix; select(STDERR); for (@ARGV) { print "\n$_:\n"; if (-f and my ($basename, $ext) = m/$rx/) { $list ? run_cmd($ext{$ext}->(archive => $_, dir => $basename)) : run_in_dir($basename, $ext{$ext}->(archive => $_, dir => $basename)); } elsif (not $list and -d) { my $basename = basename catdir $_; my $rootdir = quotemeta rootdir; $basename =~ s/\A$rootdir\z/rootdir/; $basename .= '.tar.bz2'; -e $basename ? print "$basename already exists\n" : run_cmd(tar => c => '--bzip2', -f => $basename, $_); } else { print "\tNo handler found\n"; } }