5dollarwhitebox.org - theboxownsyou

  • blog
  • projects
  • articles
  • tech wiki
  • about
  • login
Home › Python: Making '.bak' Files/Directories Without Clobbering Existing Ones

RSS Feed

Reply to comment

Python: Making '.bak' Files/Directories Without Clobbering Existing Ones

drks — Mon, 2009-07-20 19:11

Inevitably we all need to read/write new files and modify existing files. When scripting for different projects, I almost always need to update a configuration file here or drop something into a system file there (like /etc/hosts or similar). The first thing you want to do however is make a safe backup of whatever file you are modifying before you alter it.

To safely backup a file isn't a complicated task, but sometimes it gets overlooked. Sure, I can rename a file or directory with one line of code... but what if the 'backup' path already exists? Then you'd be overwriting a previous backup. Maybe one that another sysadmin made... and needs. And what if, there is a backup of that backup? You can see that there are any number of things to consider if you really care about data integrity and not borking someone else's backups (if your on a system with multiple administrators). That said, adding a simple function to your scripts can save you a lot of time and headache by just ensuring you don't overwrite existing data.

The following function will take a path, and make a copy of it to '.bak' or '.bak.X' where X is a safe extension to avoid overwriting another similar file. Alternatively, the 'keep_original=False' will make the function move ithe file out of place rather than copying it.

import os
import shutil
 
def safe_backup(path, keep_original=True):
    """
    Rename a file or directory safely without overwriting an existing 
    backup of the same name.
    """
    count = -1
    new_path = None
    while True:
        if os.path.exists(path):
            if count == -1:
                new_path = "%s.bak" % (path)
            else:
                new_path = "%s.bak.%s" % (path, count)
            if os.path.exists(new_path):
                count += 1
                continue
            else:
                if keep_original:
                    if os.path.isfile(path):
                        shutil.copy(path, new_path)
                    elif os.path.isdir(path):
                        shutil.copytree(path, new_path)
                else:
                    shutil.move(path, new_path)
                break
        else:
            break
    return new_path



The following script shows it in action:

for i in xrange(10):
    path='./johnny'
    bak_path = safe_backup(path)
    if bak_path:
        print '%s safely backed up as %s' % (path, bak_path)
    else:
        print '%s does not exist, nothing to backup' % path
    f = open(path, 'w')
    f.write('data for file %s' % i)
    f.close()



And the output:

wdierkes@slice01 [~] $ python safe_backup_example.py
./johnny does not exist, nothing to backup
./johnny safely backed up as ./johnny.bak
./johnny safely backed up as ./johnny.bak.0
./johnny safely backed up as ./johnny.bak.1
./johnny safely backed up as ./johnny.bak.2
./johnny safely backed up as ./johnny.bak.3
./johnny safely backed up as ./johnny.bak.4
./johnny safely backed up as ./johnny.bak.5
./johnny safely backed up as ./johnny.bak.6
./johnny safely backed up as ./johnny.bak.7



Keep your scripts safe... keep your sanity... everyone's happy.



‹ Python: Howto Use Just Email Addresses as User Names in TurboGears 2.0 up Python: Setting up a TurboGears Application Under Shared Namespace ›
  • drks's blog
  • Printer-friendly version

Reply

The content of this field is kept private and will not be shown publicly.
Input format
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Lines and paragraphs break automatically.
  • Lines and paragraphs break automatically.
  • You can enable syntax highlighting of source code with the following tags: <code>, <blockcode>, <bash>, <c>, <cpp>, <diff>, <drupal5>, <drupal6>, <java>, <javascript>, <mysql>, <perl>, <php>, <python>, <ruby>. Beside the tag style "<foo>" it is also possible to use "[foo]".

More information about formatting options



Who's online

There are currently 0 users and 1 guest online.
  • blog
  • projects
  • articles
  • tech wiki
  • about
  • login

5dollarwhitebox.org is not responsible in anyway for actions performed based on information found on this site.