Link to home
Start Free TrialLog in
Avatar of thebourneid
thebourneid

asked on

Perl Tar Archive

I want to implement the following:
Achive all $File::Find::name files
Strip them from their full path names
After archive - delete all $File::Find::name
Delete empty folders

Something is wrong with the code because it renames only one file when using "$tar->rename($fn, $fd.'/'.$file);", or archives only one file, and every time gives me warning messages.

How to change it to process all files.
use strict;
use warnings;
use Archive::Tar;
use File::Find;


my $dir_source = 'test';

my @files = ();

find(\&archive, $dir_source); 
sub archive {
	/\.txt$/ or return;
	my $fd = $File::Find::dir;
	my $fn = $File::Find::name;
	my $file = $_;
	
	chdir("$dir_source") or die "could not cd to dir: $!";
	
	print "found $fn\n" ;
	
	$fd =~ s{^\Q$dir_source}{};
	
	push @files, $fn;	
	
	my $tar = Archive::Tar->new();
	$tar->add_files(@files);
	$tar->rename($fn, $fd.'/'.$file);
	$tar->write($fd.'.tar');
	
	unlink $fn;
	
	finddepth(sub{rmdir},'.');

}

Open in new window

ASKER CERTIFIED SOLUTION
Avatar of Tobias
Tobias
Flag of Switzerland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of thebourneid
thebourneid

ASKER

I came accross this sample recently but didn't find it helpful.

Shoud I use $File::Find::name with your suggestion. I'm talking about hundreds of folders.

If I use
my $tar = Archive::Tar->new();
$tar->add_files( <$dir_source/*.txt> );
$tar->write('file.tar');

is not enough.

Dear,

Ok. Yes you are right this is not working.

The code attached work without problem, maybe you could reuse it for that it satisfy you.

Best Regards

#!/usr/bin/perl -w  
use strict; 
use warnings 'all'; 
use Archive::Tar; 
use File::Find; 
 
my $archive=$ARGV[0]; 
my $dir=$ARGV[1]; 
if ($#ARGV != 1) { 
    print "usage: tarcvf test.tar.gz directory\n"; 
    exit; 
} 
# Create inventory of files & directories 
my @inventory = (); 
find (sub { push @inventory, $File::Find::name }, $dir); 
# Create a new tar object 
my $tar = Archive::Tar->new(); 
$tar->add_files( @inventory ); 
# Write compressed tar file 
$tar->write( $archive, 9 );

Open in new window

SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
I've test various variations and this is most close to my needs with 2 remaining problems:

The code doesn't delete emty folders
And more importantly I don't know how to be sure that only already archived files are deleted.
use strict;
use warnings;
use Archive::Tar;
use File::Find;


my $dir_source = "test";

my @files = ();

find(\&archive, $dir_source); 
sub archive {
	/\.txt$/ or return;
	my $fd = $File::Find::dir;
	my $fn = $File::Find::name;	
	
	chdir("$dir_source") or die "could not cd to dir: $!";
	
	print "found $fn\n" ;
	
	$fd =~ s{^\Q$dir_source}{};
	$fn =~ s{^\Q$dir_source}{};
	
	push @files, $fn;	
	
	my $tar = Archive::Tar->new();
	$tar->add_files(@files);
	$tar->write($fd.'.tar');

}

find(\&del_files, $dir_source); 
sub del_files {
	/\.txt$/ or return;
	my $fd = $File::Find::dir;
	my $fn = $File::Find::name;
	
	unlink $fn;
	
	finddepth(sub{rmdir},'.');

}

Open in new window