I've never done this before so am completely in the dark.
Situation
There are several directories, full of small files which get changed often on the server.
Objective
To create sipped archives of each directory and email each one to the site owner.
What to do
I have Archive::zip and Compress::Zlib (which I guess are used for this) on my local testbed server (Indigo Perl on PC) and on the live server.
Each back up would be initiated from an admin center by clicking the relevant button for that folder.
I did try a simple script (to see what happened on Indigo Perl) that zips a file in a folder, but the zipfile was empty. That's as far as I've got.
I've managed to get the script that failed, to partially work
Code:
#### ---- Back up files in .zip
use Archive::Zip;
use CGI::Carp qw(warningsToBrowser fatalsToBrowser);
print "Content-type: text/html\n\n";
#### ---- variables/settings
$foldertobup = "data";
$zipfilename = "test";
#### ---- Process
$obj = Archive::Zip->new();
# files to store, but I need to each name first.
@files = ("$foldertobup/datone.txt",
"$foldertobup/dattwo.txt");
# create the zipped file
foreach $file (@files) {$obj->addFile($file);}
if ($obj->writeToFileNamed("$zipfilename.zip") != AZ_OK) {
print "Error in archive creation!";
} else {
print "Archive created successfully!";
}
exit;
It does zip up the folder, but I have to name the files inside it first. I tried a grep to no avail (may have done it wrong). Should I read the directory and put all the file names into an array beforehand? Or is there an easier way to do that?
I've managed to get all files in a directory by changing:
Code:
@files = ("$foldertobup/datone.txt",
"$foldertobup/dattwo.txt");
to
@files = <$foldertobup/*>;
That's good. How do I get all the sub directories as well?
I guess everyone is on vacation at the moment as I see no replies.
You need a recursive function.
Code:
sub processDir {
my $inDir = shift @_;
opendir(DIR, $inDir) or die "$!: Error open directory $inDir !";
while (my $file = readdir(DIR)) {
next if $file =~ /^\./;
next if $file =~ /\.zip$/i; #assume you don't want to process zip file
if (-f "$inDir/$file") {
#this is a file
} elsif (-d "$inDir/$file") { #this is a directory
processDir("$inDir/$file"); #recursive call
}
}
closedir(DIR);
}
sohguanh, I can see that zipping a directory with files and sub-directories is going to be a whole 'nother ball game. The sub dirs was me having a "what if" moment - sorry.
As it stands now I can zip up a directory and it's files.
During this I realized that a date and time on the filename will be needed. This is how the script looks now.
Code:
use Archive::Zip;
use CGI::Carp qw(warningsToBrowser fatalsToBrowser);
print "Content-type: text/html\n\n";
#### ---- day and time
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
$fstim = sprintf "%4d%02d%02d%02d%02d\n", 1900+$year,$mon+1,$mday,$hour,$min;
#### ---- variables/settings
## various folder names for test
$afldr = "data";
$bfldr = "dbs";
#### ---- Key for later when libbed
$foldertobup = "$bfldr"; # change variable to input later
@files = <$foldertobup/*>; # works, files only in 1 dir.
#### below gets: Error in archive creation!
$zfn = "$foldertobup$fstim"; ## want date/time in filename
print "$zfn<br>"; ## prints okay here - so it is being seen
&createArchive; # call the sub
sub createArchive {
$obj = Archive::Zip->new();
foreach $file (@files) {$obj->addFile($file);}
if ($obj->writeToFileNamed("$zfn.zip") != AZ_OK) {
print "Error in archive creation!";
} else {
print "Archive created successfully!";
}
exit;
}
As yo can see the "$zfn" works fine during the running of the script and prints to screen (so it is there). However adding that to the zipping process causes an error.
I've tried putting it in at various points but still get the error. Am I missing something?
I have never use the Archive::Zip module before but one simple way to troubleshoot is to instead of $zfn, you first hard-code a fixed filename to see if it works or not.
if ($obj->writeToFileNamed("$zfn.zip") != AZ_OK) {
Change above line to below and see if it still fail or succeed
if ($obj->writeToFileNamed("testing.zip") != AZ_OK) {
I've had to hold fire on the date-time thing because this module does not like paths. If a directory with files is in the same directory as the script, everything will work as I've done it.
But - if the directory to back up is somewhere else and I use a path (say /one/two/three/four/five etc., the thing falls apart.
I took a look at the documentation on CPAN and it's as clear as mud.
The script is one I found. So I'll keep looking to see if there are any others that might be a starting point for me.
It looks like this is going to take ages to sort out, so I'll stop the thread here. Maybe there's another way to zip up files than having to depend on just one module.
Got the date resolved, but have had no end of trouble with the zipped file. Unzipped, it contained empty folders for each step in the path to the folder I backed up.
Evidently, "Archive Zip" cannot filter these out. To do that you need: "File Find" and "File Spec Functions qw" modules as well. A small bit of code found by searching differently yielded it and I've got it so that I have exactly what I want in the zipped file
Bookmarks