use Archive::Zip; use Archive::Zip::Tree; use File::Temp; use File::Basename; my $zip = Archive::Zip->new(); $zip->read($target) and die "can't read $target\n" if -f $target; $zip->addTree($project_root, $project_root); if (-f $target) # existing file? { my ($tmpfh, $tmpname) = File::Temp::tempfile( DIR => dirname($target)); $zip->writeToFileHandle( $tmpfh ) and die "Can't write to $tmpname\n"; $tmpfh->close(); unlink($target) or die "can't remove $target: $!\n"; rename($tmpname, $target) or die "can't rename $target: $!\n"; } else { $zip->writeToFileNamed($target) and die "can't write to $target\n"; }