''' A simple pythontool to sync two folders (or harddrives) Copyright (C) 2018 Yannis Gerlach aka MrBesen This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . ''' import os from shutil import copy2 sync1 = '/home/yannis/Projects/ownsync/test/s1/' sync2 = '/home/yannis/Projects/ownsync/test/s2/' dataname = '.sync' def endwithslash(str): if str[:-1] == '/': return str return str + '/' def readfiletoarray(file): try: f = open(file, 'r') data = f.readlines() f.close() return data except Exception as e: print('Error reading sync data', e) return [] def shouldsync(fromfile, tofile, dataf, datat): if os.path.exists(tofile): return getlastchange(tofile) < getlastchange(fromfile) # only if source file is newer elif tofile in dataf: # should nver be the case return False # file existed once, but was deleted on source elif tofile in datat: # file was synced once, but deleted on target. return False return True # file dont exists and never existed def getlastchange(file): return os.path.getmtime(file) def scandir(dir): data = [] for file in os.listdir(dir): if os.path.isfile(dir + file): data.append(dir + file) else: data.append(dir + file) for f in scandir(dir + file + '/'): data.append(f) return data def rm(path): if os.path.isfile(path): os.remove(path) else: os.rmdir(path) def updatedata(path): data = scandir(path) f = open(path + dataname, 'w+') for d in data: d = d[len(path):] if d != dataname: f.write(d + '\n') f.close() def syncnew(fro, to): #read data dataf = readfiletoarray(fro + dataname) datat = readfiletoarray(to + dataname) print(len(dataf), 'nodes loaded.') listffiles = scandir(fro) #remove prefix pos = -1 for i in range(0, len(listffiles)): listffiles[i] = listffiles[i][len(fro):] if listffiles[i] == dataname: # remove .sync file from list pos = i if pos > -1: del listffiles[pos] for f in listffiles: print('syncing: ', f) if (not os.path.isfile(fro + f)) and os.path.exists(fro + f): # TODO: check if folder was deleted at target. if not os.path.exists(to + f): # seperate if to not enter elif # print('make dir:', to + f) #if is folder and exists in from then create folder in to. os.makedirs(to + f) elif shouldsync(fro + f, to + f, dataf, datat): folder = to + f folder = folder[:folder.rfind('/')+1] # print('make required dir:', folder) if not os.path.exists(folder): os.makedirs(folder) print(fro + f, '->', to + f) copy2(fro + f, to + f) else: print('skipping', f) # delete files, that were deleted on source for f in dataf: f = f[:-1] # remove trailing \n if not os.path.exists(fro + f): print('delete file', to + f) # rm(fro + f) #MAIN #setup sync1 = endwithslash(sync1) sync2 = endwithslash(sync2) sync1ex = True if os.path.exists(sync1): updatedata(sync1) else: sync1ex = False sync2ex = True if os.path.exists(sync2): updatedata(sync2) else: sync2ex = False if not sync1ex and not sync2ex: print('both folders do not exists, exiting.') else: print('Location A: ', sync1, '\nLocation B: ', sync2) if sync1ex: print('Sync A -> B') syncnew(sync1, sync2) print('update changes.') updatedata(sync2) # update changes print('Done.') if sync2ex: print('Sync B -> A') syncnew(sync2, sync1) print('update changes.') updatedata(sync1) # update changes print('Done.') print('Done.')