#! /usr/bin/env python # -*- coding: utf-8 -*- ###################################################### # # snapshot - take a snapshot of a given directory, and archive it compressed. # - toma una instantánea del directorio dado, y la guarda comprimida. # # Copyright © 2003,2004,2005,2006,2007,2008 Alberto González Palomo # Author: Alberto González Palomo # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # ###################################################### import sys import os import getopt import time import re def display_help(): print ''' Usage: snapshot [options] [directory]... Package the directory contents to a "tar" file compressed with bzip2, and named as "directory_yyyymmdd_hhmm.tbz2", where "directory" is the directory name given, "yyyymmdd" is the current date, and "hhmm" is the current time. The archive file permissions are set to 440 (not writable) to make accidental deletion a bit more difficult. The directory name gets striped in the tar file so that when untarring, the result will be just the last part of the directory path: e.g., if you ask to take a snapshot of directory "foo/bar/baz", the tar file will have the contents of "baz", and extract them to a directory named "baz", without "foo/bar". This is done to properly manage requests such as "../../foo", wich will produce a snapshot of "foo" that extracts to "foo/" in the current directory. If no directory is given, the snapshot gets the current one: e.g., if you are in "/home/foo/projects/bar/", and type just "snapshot", you will get a snapshot that extracts to "bar/", and is named "bar_yyyymmdd_hhmm.tbz2". -h, --help Display this message. -l, --label Extra label to add to the archive file name. -t, --just-test Do not actually execute tar. -x, --exclude=pattern Files to exclude, separated by commas. For instance, to exclude all .svn and .cvs directories and all C object files: --exclude=.svn,.cvs,'*.o' -d, --snapshot-path=directory Snapshots directory. Default is "~/snapshots". This can also be set with the environment variable "SNAPSHOTS_PATH". If this directory does not exist, it will be created. Report bugs to matmota@matracas.org ''' def main(): try: snapshots_path = os.environ['SNAPSHOTS_PATH'] except: snapshots_path = '~/snapshots' label = "" just_test = 0 exclude_pattern = "" try: opts, args = getopt.getopt(sys.argv[1:], 'hd:l:tx:', ('help', 'snapshots-dir=', 'label=', 'just-test', 'exclude=')) except getopt.error, option: print 'Command line option problem: ', option, '\n' display_help() return(1) for o, a in opts: if (o == '-d')|(o == '--snapshots-dir'): snapshots_path = a if (o == '-l')|(o == '--label'): label = a if (o == '-t')|(o == '--just-test'): just_test = 1 if (o == '-x')|(o == '--exclude'): exclude_pattern = a if (o == '-h')|(o == '--help'): display_help() return(0) if not args: args = ['.'] if label: label = re.sub(r'[ \t\n();:,./\\]', r'_', label) snapshots_path = os.path.expanduser(snapshots_path) try: os.stat(snapshots_path) except os.error, problem: if (str(problem)[:9] == "[Errno 2]"): print 'Making new directory:', snapshots_path if not just_test: os.makedirs(snapshots_path) for directory in args: while (directory[-1:] == "/"): directory = directory[:-1] directory = os.path.abspath(directory) date = time.strftime("_%Y%m%d_%H%M", time.localtime(time.time())) snapshot_base_name = os.path.abspath(directory) snapshot_base_name = os.path.basename(snapshot_base_name) snapshot_name = os.path.abspath(snapshots_path + '/' + snapshot_base_name) if label: snapshot_name = snapshot_name + date + '.' + label + '.tbz2' else: snapshot_name = snapshot_name + date + '.tbz2' directory_tail = os.path.basename(directory) directory_head = os.path.dirname(directory) command = 'tar jcvf "' + snapshot_name + '"' if exclude_pattern: for pattern in exclude_pattern.split(","): command += " --exclude '" + pattern + "'" if (directory_head != ""): command = ('cd "' + directory_head + '"; ' + command) command = command + ' "' + directory_tail command = command + '"; chmod 440 "' + snapshot_name + '"' print command if not just_test: os.system(command) print "Stored in", snapshot_name main()