# apollias-zip-backup-script-for-windows.pl # # by Apollia of Astroblahhh.Com. http://astroblahhh.com/ # # Completed 8/24/2011. # # Public domain. # # # This script makes it easy to make zipped backups of whatever files # and folders you want. After you get everything set up by following # the instructions below, you can run this script just by # double-clicking it. # # This version of this script is designed for use in Windows. I've only # tested it in Windows XP. It assumes that paths begin with a drive # letter followed by a :/ - so, I guess that's probably the main reason # it might not work in Linux. Haven't tested it in Linux yet. # # # There is a version of this script that definitely works in the # Lucid Puppy 5.2 variety of Puppy Linux, and which might work ( # with slight modifications) in other kinds of Linux. # # It's here somewhere: # # http://astroblahhh.com/linux.shtml # ########################################################################## # # # Instructions # # # * To run this Perl script, you need to have Perl installed on your computer. # There are probably other ways to install Perl besides downloading the # free ActivePerl installer, but, I'm too lazy to research them. # # http://www.activestate.com/activeperl # # # * This Perl script uses two Perl modules - Archive::Zip (essential) # and File::Copy (needed if you have the script make a temporary zip # file which is then copied to the final location). # # Hopefully those modules are automatically included with your Perl # installation. If not, you'll have to figure out how to install them. # # Sorry, I forgot how I typically used to install new Perl modules - I haven't # used Windows Perl very much in a while. # # # * If the name of this script file ends in ".txt", change it to ".pl" if you # want to be able to run it by double-clicking it. # # # * Open this script in a text editor. # # # * Go the section titled "Variables you need (or might need) to change", # and follow the instructions there. # # # * After all that - to run this script, you should be able to just double-click # on it. # # If it worked, an small black window titled something like C:\Perl\bin\perl.exe # containing various informative text should pop up. # # Possibly within just seconds (depending on how much stuff you zip), # your zip file ought to be output to the folder path you specified in # $final_location_for_zip_file. # # # If the window vanishes seconds after it opens, an error occurred. # Perhaps you put in a typo and it's causing an error. # # If you would like to see what error is happening, follow these steps to # run this script from a command prompt window that won't close # immediately after the script encounters an error: # # * Go to the Start menu, # # * Choose "Run..." # # * In the little window titled Run that appeared, type "cmd.exe" and click OK. # That should cause a small black window titled something like # "C;\WINDOWS\system32\cmd.exe" to appear. # # That window will give you a command prompt which should look # something like this: # # C:\Documents and Settings\etc1> # # "C:\Documents and Settings\etc1" is the current directory you're in. # # * Next, go the directory this script is in by using the "cd" command. # ("cd" is short for "change directory"). # # Assuming the command prompt says you're currently at a location # on the C: drive - then, if this script were on the C: drive and in a # folder named "blah", you would type this command to go to that # folder: # # cd C:\blah # # If this script were on some other drive than C:, for example, # D:\blah, then, you would use this command to go there: # # cd \d D:\blah # # In Windows, unlike Linux, there's no need to properly capitalize # the directory names. # # * Once the command prompt says you're in the directory of this script, # you can run this script just by typing its name, if the script name ends # in .pl. # # If the script's name doesn't end in .pl, then, you'll have to type "perl" # before the script name. ################################################################ # # Stuff you can leave alone # use Cwd 'abs_path'; $this_script_path=abs_path($0); $this_script_path=~s/ /\\ /g; $escaped_script_path=$this_script_path; $lastslashpos=rindex($this_script_path, "/"); $script_name=substr($this_script_path, $lastslashpos+1); print "Running $this_script_path...\n\n\n"; # # ################################################################ use Archive::Zip; # http://search.cpan.org/~adamk/Archive-Zip-1.30/lib/Archive/Zip.pm my $zip = Archive::Zip->new(); ####################################################################### # # Variables you need (or might need) to change # # # Both of the next two variables should be set to a folder path like # "D:/temp/", and not a file path (like "D:/temp/Backup.zip"). # # Though Windows generally uses backslashes - \ - for file paths, use # forward slashes - / - for the file paths below. # # No need to end the paths with a slash, but you can if you want. $temp_location_for_zip_file="Q:/"; # Use forward slashes - / - instead of backslashes: \ # I ike to use a temporary location in a RAM disk I create in Windows # using the software ImDisk. # # Here's where you can get ImDisk: # # http://www.ltr-data.se/opencode.html/ # # That way, the script doesn't write anything to my physical # disk drive until the zip file is completely built. # # That's particularly useful with a Flash drive, because Flash # drives can only be used for a limited number of writes, # so it's good to minimize the number of writes you do. # # A quote from http://en.wikipedia.org/wiki/USB_flash_drive#Longevity - # # "Barring physical destruction of the drive, the memory # or USB connector of a flash drive will eventually fail. SLC # based memory is good for around 100,000 writes; more commonly # used MLC for around 10,000." #$final_location_for_zip_file="Q:/final"; $final_location_for_zip_file="T:/Backups"; # Use forward slashes - / - instead of backslashes: \ $make_zip_file_in_temp_location_then_copy_to_final_location_for_zip_file="true"; # If true, the script builds the zip file at the path you provided in # $temp_location_for_zip_file, and when it's finished building that # zip file, it copies it to the path you provided in # $final_location_for_zip_file. # # If false, the script doesn't do anything with # $temp_location_for_zip_file and builds the zip file # at $final_location_for_zip_file. $open_zip_file_folder_when_script_is_finished = "true"; # If true, the script will use Internet Explorer to open the folder the zip file ended up # in. # # Unfortunately, for some reason tere's an annoying glitch with this, where # you can't do anything with the Perl window anymore until you close the # folder that got opened. $add_file_or_folder_names_to_zip_file_name="true"; # If false, the zip file name will be something like: # 2011_5_22-09,30,30--Backup.zip # # If true, and you've told the script to zip some files or # folders named (for example) "Saved Files" and "abdesk", the zip # file name will be something like: # # 2011_5_22-09,30,30--Backup--Saved Files--abdesk.zip # # If the zip's file name gets longer than 100 characters, # the script will crop the file name down to 100 characters. $use_full_paths="false"; # If you want to zip two different folders by the same name in two # different locations, like "C:/stuff/Saved Files" and # "D:/stuff/Saved Files", or two different files with the same name, # it might be best to change this to true. # # Otherwise, the contents of those two folders with the same # name will get mixed together in the zip file. # # If both folders happen to contain a file named (for example) A.txt, # both A.txt files will get zipped but, when you try to unzip the file, # your unzipping software might nag you to rename the files which # have identical names. # # With the above variable set to true, the full file path (like # "D/stuff/Saved Files" or "C/stuff/Saved Files") will get stored, # instead of just "Saved Files". # Use forward slashes - / - instead of backslashes: \ @things_to_zip=( "X:/xampp/htdocs/abdesk/", "Z:/Table" ); # In the above array, put the paths of folders and/or files you # wish to zip. # # Use forward slashes - / - instead of backslashes: \ # # # Unnecessary tip: # # If your paths go to a folder, then, you can end your path with # a slash to show that it's a path to a folder. # # However, this script will still work even if you don't include # a last slash. $halt_script_if_any_things_to_zip_dont_exist= "true"; # If true, the script will halt if it finds any of the files and # folders listed in @things_to_zip don't exist. # # If false, the script will just go ahead and create the zip file without the # missing files/folders. # # # End of variables you need (or might need) to change. # # Beyond this point, nothing else really needs to be changed. # ######################################################################## #################################################################### # # Variables, etc. you should probably leave alone # # my @nonexistent_paths; if ($make_zip_file_in_temp_location_then_copy_to_final_location_for_zip_file eq "true") { CheckForZipDestPathErrors("temp_location_for_zip_file"); $temp_location_for_zip_file=AddSlashIfNeeded($temp_location_for_zip_file); # Conveniently adds a slash to the end, if the user forgot. } CheckForZipDestPathErrors("final_location_for_zip_file"); $final_location_for_zip_file=AddSlashIfNeeded($final_location_for_zip_file); if ($make_zip_file_in_temp_location_then_copy_to_final_location_for_zip_file eq "true") { use File::Copy; } sub CheckForZipDestPathErrors { $var=$_[0]; if (!-e $$var) { print "Sorry, the folder provided in the $var variable doesn't exist. Please create it at $$var and run this script again."; PressReturnToCloseWindow(); } if (!-d $$var) { print "Sorry, the path provided in the $var variable leads to a file, not a directory. Please put a different path in $var, or change $$var to a directory, and run this script again."; PressReturnToCloseWindow(); } } sub AddSlashIfNeeded { $this_string=$_[0]; $lastchar = substr($this_string,length($this_string)-1,1); if ($lastchar ne "/") { $this_string .= "/"; } return $this_string; } @timeData = localtime(time); #print join(' ', @timeData); ($second, $minute, $hour, $dayOfMonth, $month, $yearOffset, $dayOfWeek, $dayOfYear, $daylightSavings) = localtime(time); $year = 1900 + $yearOffset; $month = $month + 1; $second = sprintf("%02d", $second); $minute = sprintf("%02d", $minute); $hour = sprintf("%02d", $hour); $zipfile_name=$year . "_" . $month . "_" . $dayOfMonth . "-" . $hour . "," . $minute . "," . $second . "--Backup"; my %paths_and_file_or_folder_name; $string_of_dirs_to_zip=""; # # End of variables, etc. you should probably leave alone # #################################################################### ################################################################### # # More stuff that doesn't need to be changed. # # foreach $thing_to_zip (@things_to_zip) { $len=length($thing_to_zip); $second_rightmost_slash_loc=rindex($thing_to_zip, "/", $len-2); $parentdirs=substr($thing_to_zip, 0, $second_rightmost_slash_loc+1); $file_or_folder_name=substr($thing_to_zip, $second_rightmost_slash_loc+1); $length_of_file_or_folder_name=length($file_or_folder_name); if (substr($file_or_folder_name, $length_of_file_or_folder_name-1, 1) eq "/") #If the last character is "/"... { chop($file_or_folder_name); #...get rid of it. } $this_full_path=$parentdirs . $file_or_folder_name; if (!-e $this_full_path) { push (@nonexistent_paths, $this_full_path); } $parentdirs_and_file_or_folder_name{$this_full_path}=[$parentdirs, $file_or_folder_name]; if ($add_file_or_folder_names_to_zip_file_name eq "true") { $zipfile_name = $zipfile_name . "--$file_or_folder_name"; } } if (@nonexistent_paths) { print "Nonexistent file(s) or folder(s) listed in things_to_zip array!\n\n"; foreach $nonexistent_path (@nonexistent_paths) { print " $this_full_path\n"; } print "\n\nHalting script. No zip file created."; PressReturnToCloseWindow(); } if ($use_full_paths eq "true") { print "Using full paths for files in zip file."; } else { print "Using short paths for files in zip file."; } print "\n"; $length_of_zipfile_name=length($zipfile_name); if ($length_of_zipfile_name>96) { $zipfile_name=substr($zipfile_name, 0, 96); } $zipfile_name=$zipfile_name . ".zip"; if ($make_zip_file_in_temp_location_then_copy_to_final_location_for_zip_file eq "true") { $zip_file_path=$temp_location_for_zip_file . $zipfile_name; } else { $zip_file_path=$final_location_for_zip_file . $zipfile_name; } $final_zip_file_path=$final_location_for_zip_file . $zipfile_name; print "\n\nTrying to back up these paths:\n\n\n"; foreach $fullpath (keys %parentdirs_and_file_or_folder_name) { $array_reference = $parentdirs_and_file_or_folder_name{$fullpath}; @the_array=@$array_reference; $path=$the_array[0]; $file_or_folder=$the_array[1]; if ($use_full_paths eq "false") { chdir $path; if (-f $fullpath) { $zip->addFile( "$fullpath", "$file_or_folder" ); print "$fullpath Zipped file!\n\n"; } elsif (-d $fullpath) { $zip->addTree( "$fullpath", "$file_or_folder" ); print "$fullpath/ Zipped folder!\n\n"; } elsif (!-e $fullpath) { print "$fullpath FILE OR FOLDER NOT FOUND!\n\n"; } } elsif ($use_full_paths eq "true") { $colonless_path=$path; $colonless_path=~s/://g; $destpath=$colonless_path . $file_or_folder; if (-f $fullpath) { $zip->addFile( "$fullpath", "$destpath" ); } elsif (-d $fullpath) { $zip->addTree( "$fullpath", "$destpath" ); } elsif (!-e $fullpath) { print "$fullpath FILE OR FOLDER NOT FOUND!\n\n"; } } } print "\n"; if ($make_zip_file_in_temp_location_then_copy_to_final_location_for_zip_file eq "true") { chdir $temp_location_for_zip_file; } else { chdir $final_location_for_zip_file; } unless ( $zip->writeToFileNamed("$zipfile_name") == AZ_OK ) { print "\n\nFor some reason, failed to output the zip file at all anywhere. Sorry."; PressReturnToCloseWindow(); } $zip_file_path_to_display=$zip_file_path; if ($make_zip_file_in_temp_location_then_copy_to_final_location_for_zip_file eq "true") { if (!-e $final_zip_file_path) { if ( copy($zip_file_path, $final_zip_file_path)) { # We attempt the copy. # If it succeeded, we report that. print "\n\nSuccessfully copied temp zip to final location: $zip_file_path -> $final_zip_file_path\n"; $zip_file_path_to_display=$final_zip_file_path; } else { # If it failed, we report that. print "\n\nFailed to copy temp zip to final location: $zip_file_path -> $final_zip_file_path $!\n"; } } else { # If a file already exists at the destination... print "\nA file already exists at $final_zip_file_path - so didn't copy the temp zip from $zip_file_path to $final_zip_file_path.\n"; } } print "\n\nBackup finished!\n"; print "\nZip file at: $zip_file_path_to_display\n"; if ($open_zip_file_folder_when_script_is_finished eq "true") { $rightmost_slash_loc=rindex($zip_file_path_to_display, "/"); $zip_file_path_to_go_to=substr($zip_file_path_to_display, 0, $rightmost_slash_loc+1); my $pid = fork(); if ($pid==0) { print "\n\nOpening zip file location, $zip_file_path_to_go_to...\n\n"; exec ("iexplore file://localhost/$final_location_for_zip_file"); } } PressReturnToCloseWindow(); # If you've rather have the window automatically disappear after the # script is finished running, comment out the previous line, and # uncomment the next 3 lines. # $secs=5; # print "\n\nThis window will automatically close in $secs seconds.\n\n\n"; # sleep $secs; sub PressReturnToCloseWindow { if ($open_zip_file_folder_when_script_is_finished eq "true" && $zip_file_path_to_display) { print "\n\n\nSince you have the open_zip_file_folder_when_script_is_finished variable set to true, you might not be able to do anything else in this window until you close the folder this script opened. I don't know how to fix this annoying glitch.\n"; } else { print "\n\n\nYou can press Return (or Enter) to close this window.\n"; } $wait_for_return = ; die; }