Skip to content

Instantly share code, notes, and snippets.

@ellockie
Forked from aortbals/dispatch.py
Last active December 28, 2015 04:53
Show Gist options
  • Save ellockie/808abbeeeee6a34aa36b to your computer and use it in GitHub Desktop.
Save ellockie/808abbeeeee6a34aa36b to your computer and use it in GitHub Desktop.
Synchronize two folders using python.
config.json
json_example as xml.xml
#! /usr/bin/python
# Dispatch - synchronize two folders (bidirectionally)
# Original author: aortbals
# Updates by ellockie:
# - added json config file support (idea by laserpez)
# - changed output formatting
import os
import filecmp
import shutil
from stat import *
class Dispatch:
''' This class represents a synchronization object '''
def __init__(self, name=''):
self.name = name
self.node_list = []
self.file_copied_count = 0
self.folder_copied_count = 0
def add_node(self, node):
self.node_list.append(node)
def compare_nodes(self):
''' This method takes the nodes in the node_list and compares them '''
nodeListLength = len(self.node_list)
# For each node in the list
for node in self.node_list:
# If the list has another item after it, compare them
if self.node_list.index(node) < len(self.node_list) - 1:
node2 = self.node_list[self.node_list.index(node) + 1]
print '\n Comparing node ' + str(self.node_list.index(node)) + ' and node ' + str(self.node_list.index(node) + 1) + '.\n'
# Passes the two root directories of the nodes to the recursive _compare_directories.
self._compare_directories(node.root_path, node2.root_path)
def _compare_directories(self, left, right):
''' This method compares directories. If there is a common directory, the
algorithm must compare what is inside of the directory by calling this
recursively.
'''
comparison = filecmp.dircmp(left, right)
if comparison.common_dirs:
for d in comparison.common_dirs:
self._compare_directories(os.path.join(left, d), os.path.join(right, d))
if comparison.left_only:
print "----------------------------------------\n Copying from LEFT to RIGHT:\n"
self._copy(comparison.left_only, left, right)
if comparison.right_only:
print "----------------------------------------\n Copying from RIGHT to LEFT:\n"
self._copy(comparison.right_only, right, left)
if comparison.diff_files:
left_newer = []
right_newer = []
print "----------------------------------------\n- There are file version differences. -"
for d in comparison.diff_files:
l_modified = os.stat(os.path.join(left, d)).st_mtime
r_modified = os.stat(os.path.join(right, d)).st_mtime
if l_modified > r_modified:
left_newer.append(d)
else:
right_newer.append(d)
if len(left_newer):
print "----------------------------------------\n Copying newer files from LEFT to RIGHT:\n"
self._copy(left_newer, left, right)
if len(right_newer):
print "----------------------------------------\n Copying newer files from RIGHT to LEFT:\n"
self._copy(right_newer, right, left)
def _display_item_message(self, srcpath, dest, is_dir):
'''Displays info about each copied item'''
if is_dir:
print ' @ Directory:\n',
print ' -', os.path.basename(srcpath) + ':'
print '\t<-- \"' + os.path.dirname(srcpath) + '\\\"'
print '\t--> \"' + dest + '\\\"\n'
def _copy(self, file_list, src, dest):
''' This method copies a list of files from a source node to a destination node '''
for f in file_list:
srcpath = os.path.join(src, os.path.basename(f))
if os.path.isdir(srcpath):
shutil.copytree(srcpath, os.path.join(dest, os.path.basename(f)))
self.folder_copied_count = self.folder_copied_count + 1
self._display_item_message(srcpath, dest, True)
else:
shutil.copy2(srcpath, dest)
self.file_copied_count = self.file_copied_count + 1
# print ' - ' + os.path.basename(srcpath) + ':'
# print '\t<-- \"' + os.path.dirname(srcpath) + '\\\"'
# print '\t--> \"' + dest + '\\\"\n'
self._display_item_message(srcpath, dest, False)
class Node:
''' This class represents a node in a dispatch synchronization '''
def __init__(self, path, name=''):
self.name = name
self.root_path = os.path.abspath(path)
self.file_list = os.listdir(self.root_path)
if __name__ == "__main__":
import json
config = json.load(open('config.json', 'rt'))
my_dispatch = Dispatch()
node1 = Node(config['node1'], 'node1')
node2 = Node(config['node2'], 'node2')
my_dispatch.add_node(node1)
my_dispatch.add_node(node2)
my_dispatch.compare_nodes()
print '\n Total files copied: ' + str(my_dispatch.file_copied_count)
print ' Total folders copied: ' + str(my_dispatch.folder_copied_count)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment