Welcome, guest | Sign In | My Account | Store | Cart
Python, 33 lines
 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
def backupSave(fileName, prefix='', suffix='bk', count=5):
     ''' backupSave: backup a file to up to number of versions defined by count.
    
     Let fileName = 'c:/tmp/myfile.txt'
         prefix   = 'x_'
         suffix   = 'BAK'
         count    = 5 
    
     This function will check if 
    
        x_myfile.txt.BAKi

    exists in the same folder, where 1<=i<=count
    
    If found, save it to x_myfile.txt.BAKi+1
    
     version: 04b43
     module : panTools    
     author : Runsun Pan
     '''
     import os, shutil
     folder, fileName = os.path.split(fileName)
     if not folder.strip(): folder = '.'
     files = os.listdir(folder)
     
     for i in range(count):
        j = count-i-1
        fn  = prefix + fileName  + '.' + suffix + str(j)
        if j == 0: fn = fileName
        nfn = prefix + fileName +  '.' + suffix + str(j+1)
        fn = os.path.join(folder, fn)
        if os.path.exists(fn):
           shutil.copy(fn, nfn) 

backupSave('myfile.txt') ===> will copy myfile.txt to myfile.txt.bk1

run it the 2nd time ==> will copy myfile.txt.bk1 to myfile.txt.bk2 and copy myfile.txt to myfile.txt.bk1

run it the 3rd time ==> copy myfile.txt.bk2 to myfile.txt.bk3 copy myfile.txt.bk1 to myfile.txt.bk2 and copy myfile.txt to myfile.txt.bk1 ... up to a number of versions defined by the argument 'count'

2 comments

Denis Barmenkov 17 years ago  # | flag

my version may be cleaner ;). Hi,

with os function wrappers this task will be more pleasant, especially for smart file handling (gaps in BAK filenames) and using rename instead of copy.

def rename_to_backup(fn, backup_amount=5, backup_ext='BAK'):

    import os.path, os

    def bak_name(i):
        if i &lt; 1: return fn
        return '%s.%s%d' % (fn, backup_ext, i)
    def exists(i):
        f = bak_name(i)
        return os.path.exists(f)
    def unlink(i):
        f = bak_name(i)
        try: os.unlink(f)
        except IOError: pass
    def rename(i, j):
        fi = bak_name(i)
        fj = bak_name(j)
        try: os.rename(fi, fj)
        except IOError: pass

    for i in range(backup_amount - 1, -1, -1):
        if exists(i):
            if exists(i-1):
                if exists(i+1): unlink(i+1)
                rename(i, i+1)
Denis Barmenkov 16 years, 10 months ago  # | flag

And smarter... this version doesnt allow 'gaps' between backup file names, and not perform extra file renames:

def rename_to_backup(fn, backup_amount=5, backup_ext='BAK'):

    import os.path, os

    def bak_name(i):
        if i &lt; 1: return fn
        return '%s.%s%d' % (fn, backup_ext, i)
    def exists(i):
        f = bak_name(i)
        return os.path.exists(f)
    def unlink(i):
        if not exists(i): return
        f = bak_name(i)
        try:
            print 'bpc.file> delete %s' % (f)
            os.unlink(f)
        except IOError, OSError:
            pass
    def rename(i, j):
        fi = bak_name(i)
        fj = bak_name(j)
        try:
            print 'bpc.file> rename %s => %s' % (fi, fj)
            os.rename(fi, fj)
        except IOError:
            pass

    def rename_one(index):
        print 'rename_one> index=%d' % index
        if index == backup_amount:
            print 'rename_one> Last Index'
            unlink(index)
        else:
            if exists(index):
                print 'rename_one>   next index: %d'  % index
                rename_one(index + 1)
                rename(index, index + 1)

    rename_one(0)