title: script to sync files from local computer to external host (sftp or ssh)
body: <p>For a project of me, I need to be able to copy the output of a program (HTML) to my server with a script, so it can be done by just launching the script, no further handling.
  The uploading should be done only for files where the content has been changed because the date is always changed after a new publish out of my program.</p>
  
  <p>I've found a script online that was able to do what I've wanted with some minor changes. Now it works when I publish between 2 folders on my computer, but I should be able to replace my destination with an sFTP or SSH connection...</p>
  
  <pre><code>import os
  import filecmp
  import shutil
  
  '''
  Version: Python 3.3.2
  Using python SyncFolder in CMD
  Origin: https://gist.github.com/aortbals/5096365
  Modified by Louisdj_15
  '''
  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
      self.file_removed_count=0
      self.folder_removed_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) + 1 &lt; len(self.node_list):
              node2 = self.node_list[self.node_list.index(node) + 1]
              '''print(str('\nComparing node ') + str(self.node_list.index(node)) + str(' and Node ') + str(self.node_list.index(node) + 1) + ':')'''
              print('Comparing localhost to server')
              # Pass 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:
          self._copy(comparison.left_only, left, right)
      if comparison.right_only:
          self._remove(comparison.right_only, right)
      left_newer = []
      right_newer = []
      if comparison.diff_files:
          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 &gt; r_modified:
                  left_newer.append(d)
              else:
                  right_newer.append(d)
      self._copy(left_newer, left, right)
      self._copy(right_newer, right, left)
  
  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
              print('Copied directory \"' + os.path.basename(srcpath) + '\" from \"' + os.path.dirname(srcpath) + '\" to \"' + dest + '\"')
          else:
              shutil.copy2(srcpath, dest)
              self.file_copied_count = self.file_copied_count + 1
              print('Copied \"' + os.path.basename(srcpath) + '\" from \"' + os.path.dirname(srcpath) + '\" to \"' + dest + '\"')
  
  def _remove(self, file_list, src):
      ''' This method removes a list of files from a destionation node if doesn't exist any longer on source '''
      for f in file_list:
          srcpath = os.path.join(src, os.path.basename(f))
          if os.path.isdir(srcpath):
              shutil.rmtree(srcpath)
              self.folder_removed_count = self.folder_removed_count + 1
              print('Removed directory \"' + os.path.basename(srcpath) + '\" from \"' + os.path.dirname(srcpath))
          else:
              os.remove(srcpath)
              self.file_removed_count = self.file_removed_count + 1
              print('Removed file \"' + os.path.basename(srcpath) + '\" from \"' + os.path.dirname(srcpath))
  
  
  class Node:
      ''' This class represents a node in a dispathc 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__":
      node_source = Node('C:\\source_folder', 'source')
      dispatch = Dispatch('Dispatcher')
      node_dest = Node('HERE I NEED AN SFTP OR SSH LINK', 'dest')
      dispatch.add_node(node_source)
      dispatch.add_node(node_dest)
      count=0
      os.system('color 2')
      os.system('cls')
      print('------------------------------------')
      print('| DISPATCHER:  |')
      print('------------------------------------')
      while (count &lt; 1):
          dispatch.compare_nodes()
          print('')
          print('Total files copied ' + str(dispatch.file_copied_count))
          print('Total folders copied ' + str(dispatch.folder_copied_count))
          print('Total files removed ' + str(dispatch.file_removed_count))
          print('Total folders removed ' + str(dispatch.folder_removed_count))
          print('')
          print('Dispatcher is done! Closing connections!')
          count = count + 1
  </code></pre>