rsync_backup /

# -*- coding: ascii
rsync-based backup with space-efficient hardlinks,
multiple generations, extra token for daily, weekly,
monthly, ... backups.

author: Thomas Waldmann
license: BSD

import os
from os.path import exists, abspath
import sys
import errno
import subprocess
import shutil
from exec_cmd import exec_shell as cmd

RSYNC = "rsync -avH --numeric-ids --link-dest=%(link_dst)s %(src)s/ %(dst)s/"

def join(path, n, token):
    if n == 0:
        # there is only ONE "0" directory, no token appended
        token = ""
    return os.path.join(path, "%d%s" % (n, token))

def rsync(src, dst, link_dst, **kw):
    """backup contents of src directory into dst directory"""
    cmd(RSYNC % dict(src=abspath(src),

def dirshift(path, n, token):
    """shift the directories below the base path:
       N-1 -> N (kill it later)
       N-2 -> N-1
       0 -> 1
       create an empty 0
    for i in range(n, 0, -1):
            os.rename(join(path, i-1, token),
                      join(path, i, token))
        except OSError as err:
            if err.errno != errno.ENOENT:
                # ignore if directory does not exist,
                # otherwise raise
    os.mkdir(join(path, 0, token))
    del_dir = join(path, n, token)
    if exists(del_dir):

def backup(src, dst, n, token="", **kw):
    """do a backup from src to dst, shifting dirs first"""
    dirshift(dst, n, token)
    rsync(src, join(dst, 0, token), join(dst, 1, token), **kw)

if __name__ == "__main__":
    if len(sys.argv) != 5:
        print "rsb N token src dst"
    n, token, src, dst = sys.argv[1:]
        backup(src, dst, int(n), token)
    except subprocess.CalledProcessError as err:
        rc = err.returncode
        rc = 0
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.