1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329
|
#!/usr/bin/perl -w
# Makes a zip file of the most recent files in a specified directory.
# By Rudi Farkas, rudif@bluemail.ch, 9 December 2000
# Usage:
# ziprecent <dir> -d <ageDays> [-e <ext> ...]> [-h] [-msvc] [-q] [<zippath>]
# Zips files in source directory and its subdirectories
# whose file extension is in specified extensions (default: any extension).
# -d <days> max age (days) for files to be zipped (default: 1 day)
# <dir> source directory
# -e <ext> one or more space-separated extensions
# -h print help text and exit
# -msvc may be given instead of -e and will zip all msvc source files
# -q query only (list files but don't zip)
# <zippath>.zip path to zipfile to be created (or updated if it exists)
#
# $Revision: 1.2 $
use strict;
use Archive::Zip qw(:ERROR_CODES :CONSTANTS);
use Cwd;
use File::Basename;
use File::Copy;
use File::Find;
use File::Path;
# argument and variable defaults
#
my $maxFileAgeDays = 1;
my $defaultzipdir = 'h:/zip/_homework';
my ($sourcedir, $zipdir, $zippath, @extensions, $query);
# usage
#
my $scriptname = basename $0;
my $usage = <<ENDUSAGE;
$scriptname <dir> -d <ageDays> [-e <ext> ...]> [-h] [-msvc] [-q] [<zippath>]
Zips files in source directory and its subdirectories
whose file extension is in specified extensions (default: any extension).
-d <days> max age (days) for files to be zipped (default: 1 day)
<dir> source directory
-e <ext> one or more space-separated extensions
-h print help text and exit
-msvc may be given instead of -e and will zip all msvc source files
-q query only (list files but don't zip)
<zippath>.zip path to zipfile to be created (or updated if it exists)
ENDUSAGE
# parse arguments
#
while (@ARGV) {
my $arg = shift;
if ($arg eq '-d') {
$maxFileAgeDays = shift;
$maxFileAgeDays = 0.0 if $maxFileAgeDays < 0.0;
}
elsif ($arg eq '-e') {
while ($ARGV[0] && $ARGV[0] !~ /^-/) {
push @extensions, shift;
}
}
elsif ($arg eq '-msvc') {
push @extensions, qw / bmp c cpp def dlg dsp dsw h ico idl mak odl rc rc2 rgs /;
}
elsif ($arg eq '-q') {
$query = 1;
}
elsif ($arg eq '-h') {
print STDERR $usage;
exit;
}
elsif (-d $arg) {
$sourcedir = $arg;
}
elsif ($arg eq '-z') {
if ($ARGV[0]) {
$zipdir = shift;
}
}
elsif ($arg =~ /\.zip$/) {
$zippath = $arg;
}
else {
errorExit("Unknown option or argument: $arg");
}
}
# process arguments
#
errorExit("Please specify an existing source directory") unless defined($sourcedir) && -d $sourcedir;
my $extensions;
if (@extensions) {
$extensions = join "|", @extensions;
}
else {
$extensions = ".*";
}
# change '\' to '/' (avoids trouble in substitution on Win2k)
#
$sourcedir =~ s|\\|/|g;
$zippath =~ s|\\|/|g if defined($zippath);
# find files
#
my @files;
cwd $sourcedir;
find(\&listFiles, $sourcedir);
printf STDERR "Found %d file(s)\n", scalar @files;
# exit ?
#
exit if $query;
exit if @files <= 0;
# prepare zip directory
#
if (defined($zippath)) {
# deduce directory from zip path
$zipdir = dirname($zippath);
$zipdir = '.' unless length $zipdir;
}
else {
$zipdir= $defaultzipdir;
}
# make sure that zip directory exists
#
mkpath $zipdir unless -d $zipdir;
-d $zipdir or die "Can't find/make directory $zipdir\n";
# create the zip object
#
my $zip = Archive::Zip->new();
# read-in the existing zip file if any
#
if (defined $zippath && -f $zippath) {
my $status = $zip->read($zippath);
warn "Read $zippath failed\n" if $status != AZ_OK;
}
# add files
#
foreach my $memberName (@files)
{
if (-d $memberName )
{
warn "Can't add tree $memberName\n"
if $zip->addTree( $memberName, $memberName ) != AZ_OK;
}
else
{
$zip->addFile( $memberName )
or warn "Can't add file $memberName\n";
}
}
# prepare the new zip path
#
my $newzipfile = genfilename();
my $newzippath = "$zipdir/$newzipfile";
# write the new zip file
#
my $status = $zip->writeToFileNamed($newzippath);
if ($status == AZ_OK) {
# rename (and overwrite the old zip file if any)?
#
if (defined $zippath) {
my $res = rename $newzippath, $zippath;
if ($res) {
print STDERR "Updated file $zippath\n";
}
else {
print STDERR "Created file $newzippath, failed to rename to $zippath\n";
}
}
else {
print STDERR "Created file $newzippath\n";
}
}
else {
print STDERR "Failed to create file $newzippath\n";
}
# subroutines
#
sub listFiles {
if (/\.($extensions)$/) {
cwd $File::Find::dir;
return if -d $File::Find::name; # skip directories
my $fileagedays = fileAgeDays($_);
if ($fileagedays < $maxFileAgeDays) {
printf STDERR "$File::Find::name (%.3g)\n", $fileagedays;
(my $filename = $File::Find::name) =~ s/^[a-zA-Z]://; # remove the leading drive letter:
push @files, $filename;
}
}
}
sub errorExit {
printf STDERR "*** %s ***\n$usage\n", shift;
exit;
}
sub mtime {
(stat shift)[9];
}
sub fileAgeDays {
(time() - mtime(shift)) / 86400;
}
sub genfilename {
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
sprintf "%04d%02d%02d-%02d%02d%02d.zip", $year+1900, $mon+1, $mday, $hour, $min, $sec;
}
__END__
=head1 NAME
ziprecent.pl
=head1 SYNOPSIS
ziprecent h:/myperl
ziprecent h:/myperl -e pl pm -d 365
ziprecent h:/myperl -q
ziprecent h:/myperl h:/temp/zip/file1.zip
=head1 DESCRIPTION
=over 4
This script helps to collect recently modified files in a source directory
into a zip file (new or existing).
It uses Archive::Zip.
=item C< ziprecent h:/myperl >
Lists and zips all files more recent than 1 day (24 hours)
in directory h:/myperl and it's subdirectories,
and places the zip file into default zip directory.
The generated zip file name is based on local time (e.g. 20001208-231237.zip).
=item C< ziprecent h:/myperl -e pl pm -d 365 >
Zips only .pl and .pm files more recent than one year.
=item C< ziprecent h:/myperl -msvc >
Zips source files found in a typical MSVC project.
=item C< ziprecent h:/myperl -q >
Lists files that should be zipped.
=item C< ziprecent h:/myperl h:/temp/zip/file1.zip >
Updates file named h:/temp/zip/file1.zip
(overwrites an existing file if writable).
=item C< ziprecent -h >
Prints the help text and exits.
ziprecent.pl <dir> -d <days> [-e <ext> ...]> [-h] [-msvc] [-q] [<zippath>]
Zips files in source directory and its subdirectories
whose file extension is in specified extensions (default: any extension).
-d <days> max age (days) for files to be zipped (default: 1 day)
<dir> source directory
-e <ext> one or more space-separated extensions
-h print help text and exit
-msvc may be given instead of -e and will zip all msvc source files
-q query only (list files but don't zip)
<zippath>.zip path to zipfile to be created (or updated if it exists)
=back
=head1 BUGS
Tested only on Win2k.
Does not handle filenames without extension.
Does not accept more than one source directory (workaround: invoke separately
for each directory, specifying the same zip file).
=head1 AUTHOR
Rudi Farkas rudif@lecroy.com rudif@bluemail.ch
=head1 SEE ALSO
perl ;-)
=cut
|