2 # Makes a zip file of the most recent files in a specified directory.
3 # By Rudi Farkas, rudif@bluemail.ch, 9 December 2000
5 # ziprecent <dir> -d <ageDays> [-e <ext> ...]> [-h] [-msvc] [-q] [<zippath>]
6 # Zips files in source directory and its subdirectories
7 # whose file extension is in specified extensions (default: any extension).
8 # -d <days> max age (days) for files to be zipped (default: 1 day)
9 # <dir> source directory
10 # -e <ext> one or more space-separated extensions
11 # -h print help text and exit
12 # -msvc may be given instead of -e and will zip all msvc source files
13 # -q query only (list files but don't zip)
14 # <zippath>.zip path to zipfile to be created (or updated if it exists)
20 use Archive::Zip qw(:ERROR_CODES :CONSTANTS);
27 # argument and variable defaults
29 my $maxFileAgeDays = 1;
30 my $defaultzipdir = 'h:/zip/_homework';
31 my ($sourcedir, $zipdir, $zippath, @extensions, $query);
36 my $scriptname = basename $0;
37 my $usage = <<ENDUSAGE;
38 $scriptname <dir> -d <ageDays> [-e <ext> ...]> [-h] [-msvc] [-q] [<zippath>]
39 Zips files in source directory and its subdirectories
40 whose file extension is in specified extensions (default: any extension).
41 -d <days> max age (days) for files to be zipped (default: 1 day)
42 <dir> source directory
43 -e <ext> one or more space-separated extensions
44 -h print help text and exit
45 -msvc may be given instead of -e and will zip all msvc source files
46 -q query only (list files but don't zip)
47 <zippath>.zip path to zipfile to be created (or updated if it exists)
57 $maxFileAgeDays = shift;
58 $maxFileAgeDays = 0.0 if $maxFileAgeDays < 0.0;
60 elsif ($arg eq '-e') {
61 while ($ARGV[0] && $ARGV[0] !~ /^-/) {
62 push @extensions, shift;
65 elsif ($arg eq '-msvc') {
66 push @extensions, qw / bmp c cpp def dlg dsp dsw h ico idl mak odl rc rc2 rgs /;
68 elsif ($arg eq '-q') {
71 elsif ($arg eq '-h') {
78 elsif ($arg eq '-z') {
83 elsif ($arg =~ /\.zip$/) {
87 errorExit("Unknown option or argument: $arg");
93 errorExit("Please specify an existing source directory") unless defined($sourcedir) && -d $sourcedir;
97 $extensions = join "|", @extensions;
103 # change '\' to '/' (avoids trouble in substitution on Win2k)
105 $sourcedir =~ s|\\|/|g;
106 $zippath =~ s|\\|/|g if defined($zippath);
113 find(\&listFiles, $sourcedir);
114 printf STDERR "Found %d file(s)\n", scalar @files;
123 # prepare zip directory
125 if (defined($zippath)) {
126 # deduce directory from zip path
127 $zipdir = dirname($zippath);
128 $zipdir = '.' unless length $zipdir;
131 $zipdir= $defaultzipdir;
134 # make sure that zip directory exists
136 mkpath $zipdir unless -d $zipdir;
137 -d $zipdir or die "Can't find/make directory $zipdir\n";
141 # create the zip object
143 my $zip = Archive::Zip->new();
146 # read-in the existing zip file if any
148 if (defined $zippath && -f $zippath) {
149 my $status = $zip->read($zippath);
150 warn "Read $zippath failed\n" if $status != AZ_OK;
155 foreach my $memberName (@files)
159 warn "Can't add tree $memberName\n"
160 if $zip->addTree( $memberName, $memberName ) != AZ_OK;
164 $zip->addFile( $memberName )
165 or warn "Can't add file $memberName\n";
170 # prepare the new zip path
172 my $newzipfile = genfilename();
173 my $newzippath = "$zipdir/$newzipfile";
176 # write the new zip file
178 my $status = $zip->writeToFileNamed($newzippath);
179 if ($status == AZ_OK) {
180 # rename (and overwrite the old zip file if any)?
182 if (defined $zippath) {
183 my $res = rename $newzippath, $zippath;
185 print STDERR "Updated file $zippath\n";
188 print STDERR "Created file $newzippath, failed to rename to $zippath\n";
192 print STDERR "Created file $newzippath\n";
196 print STDERR "Failed to create file $newzippath\n";
205 if (/\.($extensions)$/) {
206 cwd $File::Find::dir;
207 return if -d $File::Find::name; # skip directories
208 my $fileagedays = fileAgeDays($_);
209 if ($fileagedays < $maxFileAgeDays) {
210 printf STDERR "$File::Find::name (%.3g)\n", $fileagedays;
211 (my $filename = $File::Find::name) =~ s/^[a-zA-Z]://; # remove the leading drive letter:
212 push @files, $filename;
218 printf STDERR "*** %s ***\n$usage\n", shift;
227 (time() - mtime(shift)) / 86400;
231 my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
232 sprintf "%04d%02d%02d-%02d%02d%02d.zip", $year+1900, $mon+1, $mday, $hour, $min, $sec;
245 ziprecent h:/myperl -e pl pm -d 365
247 ziprecent h:/myperl -q
249 ziprecent h:/myperl h:/temp/zip/file1.zip
256 This script helps to collect recently modified files in a source directory
257 into a zip file (new or existing).
259 It uses Archive::Zip.
261 =item C< ziprecent h:/myperl >
263 Lists and zips all files more recent than 1 day (24 hours)
264 in directory h:/myperl and it's subdirectories,
265 and places the zip file into default zip directory.
266 The generated zip file name is based on local time (e.g. 20001208-231237.zip).
269 =item C< ziprecent h:/myperl -e pl pm -d 365 >
271 Zips only .pl and .pm files more recent than one year.
274 =item C< ziprecent h:/myperl -msvc >
276 Zips source files found in a typical MSVC project.
279 =item C< ziprecent h:/myperl -q >
281 Lists files that should be zipped.
284 =item C< ziprecent h:/myperl h:/temp/zip/file1.zip >
286 Updates file named h:/temp/zip/file1.zip
287 (overwrites an existing file if writable).
290 =item C< ziprecent -h >
292 Prints the help text and exits.
294 ziprecent.pl <dir> -d <days> [-e <ext> ...]> [-h] [-msvc] [-q] [<zippath>]
295 Zips files in source directory and its subdirectories
296 whose file extension is in specified extensions (default: any extension).
297 -d <days> max age (days) for files to be zipped (default: 1 day)
298 <dir> source directory
299 -e <ext> one or more space-separated extensions
300 -h print help text and exit
301 -msvc may be given instead of -e and will zip all msvc source files
302 -q query only (list files but don't zip)
303 <zippath>.zip path to zipfile to be created (or updated if it exists)
310 Tested only on Win2k.
312 Does not handle filenames without extension.
314 Does not accept more than one source directory (workaround: invoke separately
315 for each directory, specifying the same zip file).
320 Rudi Farkas rudif@lecroy.com rudif@bluemail.ch