设为首页 收藏本站
查看: 519|回复: 0

[经验分享] python实现的一个文件同步模块

[复制链接]

尚未签到

发表于 2018-8-9 08:18:14 | 显示全部楼层 |阅读模式
Advanced Directory Synchronization module
  来源地址:http://snipperize.todayclose.com/snippet/py/Advanced-Directory-Synchronization-module--143151/
  


  • """ pyrobocopy.py -

  •     Version: 1.0

  •     Report the difference in content
  •     of two directories, synchronize or
  •     update a directory from another, taking
  •     into account time-stamps of files etc.

  •     By Anand B Pillai

  •     (This program is inspired by the windows
  •     'Robocopy' program.)

  •     Mod  Nov 11 Rewrote to use the filecmp module.
  • """

  • import os, stat
  • import time
  • import shutil
  • import filecmp

  • def usage():
  •     return """
  • Pyrobocopy: Command line directory diff, synchronization, update & copy

  • Author: Anand Pillai

  • Usage: %s <sourcedir> <targetdir> Options

  • Main Options:\n
  • \t-d --diff         - Only report difference between sourcedir and targetdir
  • \t-s, --synchronize - Synchronize content between sourcedir and targetdir
  • \t-u, --update      - Update existing content between sourcedir and targetdir

  • Additional Options:\n
  • \t-p, --purge       - Purge files when synchronizing (does not purge by default).
  • \t-f, --force       - Force copying of files, by trying to change file permissions.
  • \t-n, --nodirection - Update files in source directory from target
  • \t                    directory (only updates target from source by default).
  • \t-c, --create      - Create target directory if it does not exist (By default,
  • \t                    target directory should exist.)
  • \t-m, --modtime     - Only compare file's modification times for an update (By default,
  • \t                    compares source file's creation time also).
  • &quot;&quot;&quot;



  • class PyRobocopier:
  •     &quot;&quot;&quot; An advanced directory synchronization, updation
  •     and file copying class &quot;&quot;&quot;

  •     prog_name = &quot;pyrobocopy.py&quot;

  •     def __init__(self):

  •         self.__dir1 = ''
  •         self.__dir2 = ''
  •         self.__dcmp = None

  •         self.__copyfiles = True
  •         self.__forcecopy = False
  •         self.__copydirection = 0
  •         self.__updatefiles = True
  •         self.__creatdirs = True
  •         self.__purge =False
  •         self.__maketarget =False
  •         self.__modtimeonly =False
  •         self.__mainfunc = None

  •         # stat vars
  •         self.__numdirs =0
  •         self.__numfiles =0
  •         self.__numdelfiles =0
  •         self.__numdeldirs =0
  •         self.__numnewdirs =0
  •         self.__numupdates =0
  •         self.__starttime = 0.0
  •         self.__endtime = 0.0

  •         # failure stat vars
  •         self.__numcopyfld =0
  •         self.__numupdsfld =0
  •         self.__numdirsfld =0
  •         self.__numdelffld  =0
  •         self.__numdeldfld  =0

  •     def parse_args(self, arguments):
  •         &quot;&quot;&quot; Parse arguments &quot;&quot;&quot;

  •         import getopt

  •         shortargs = &quot;supncm&quot;
  •         longargs = [&quot;synchronize=&quot;, &quot;update=&quot;, &quot;purge=&quot;, &quot;nodirection=&quot;, &quot;create=&quot;, &quot;modtime=&quot;]

  •         try:
  •             optlist, args = getopt.getopt( arguments, shortargs, longargs )
  •         except getopt.GetoptError, e:
  •             print e
  •             return None

  •         allargs = []
  •         if len(optlist):
  •             allargs = [x[0] for x in optlist]

  •         allargs.extend( args )
  •         self.__setargs( allargs )

  •     def __setargs(self, argslist):
  •         &quot;&quot;&quot; Sets internal variables using arguments &quot;&quot;&quot;

  •         for option in argslist:
  •             if option.lower() in ('-s', '--synchronize'):
  •                 self.__mainfunc = self.synchronize
  •             elif option.lower() in ('-u', '--update'):
  •                 self.__mainfunc = self.update
  •             elif option.lower() in ('-d', '--diff'):
  •                 self.__mainfunc = self.dirdiff
  •             elif option.lower() in ('-p', '--purge'):
  •                 self.__purge = True
  •             elif option.lower() in ('-n', '--nodirection'):
  •                 self.__copydirection = 2
  •             elif option.lower() in ('-f', '--force'):
  •                 self.__forcecopy = True
  •             elif option.lower() in ('-c', '--create'):
  •                 self.__maketarget = True
  •             elif option.lower() in ('-m', '--modtime'):
  •                 self.__modtimeonly = True
  •             else:
  •                 if self.__dir1=='':
  •                     self.__dir1 = option
  •                 elif self.__dir2=='':
  •                     self.__dir2 = option

  •         if self.__dir1=='' or self.__dir2=='':
  •             sys.exit(&quot;Argument Error: Directory arguments not given!&quot;)
  •         if not os.path.isdir(self.__dir1):
  •             sys.exit(&quot;Argument Error: Source directory does not exist!&quot;)
  •         if not self.__maketarget and not os.path.isdir(self.__dir2):
  •             sys.exit(&quot;Argument Error: Target directory %s does not exist! (Try the -c option).&quot; % self.__dir2)
  •         if self.__mainfunc is None:
  •             sys.exit(&quot;Argument Error: Specify an action (Diff, Synchronize or Update) &quot;)

  •         self.__dcmp = filecmp.dircmp(self.__dir1, self.__dir2)

  •     def do_work(self):
  •         &quot;&quot;&quot; Do work &quot;&quot;&quot;

  •         self.__starttime = time.time()

  •         if not os.path.isdir(self.__dir2):
  •             if self.__maketarget:
  •                 print 'Creating directory', self.__dir2
  •                 try:
  •                     os.makedirs(self.__dir2)
  •                 except Exception, e:
  •                     print e
  •                     return None

  •         # All right!
  •         self.__mainfunc()
  •         self.__endtime = time.time()

  •     def __dowork(self, dir1, dir2, copyfunc = None, updatefunc = None):
  •         &quot;&quot;&quot; Private attribute for doing work &quot;&quot;&quot;

  •         print 'Source directory: ', dir1, ':'

  •         self.__numdirs += 1
  •         self.__dcmp = filecmp.dircmp(dir1, dir2)

  •         # Files & directories only in target directory
  •         if self.__purge:
  •             for f2 in self.__dcmp.right_only:
  •                 fullf2 = os.path.join(dir2, f2)
  •                 print 'Deleting ',fullf2
  •                 try:
  •                     if os.path.isfile(fullf2):

  •                         try:
  •                             os.remove(fullf2)
  •                             self.__numdelfiles += 1
  •                         except OSError, e:
  •                             print e
  •                             self.__numdelffld += 1
  •                     elif os.path.isdir(fullf2):
  •                         try:
  •                             shutil.rmtree( fullf2, True )
  •                             self.__numdeldirs += 1
  •                         except shutil.Error, e:
  •                             print e
  •                             self.__numdeldfld += 1

  •                 except Exception, e: # of any use ?
  •                     print e
  •                     continue


  •         # Files & directories only in source directory
  •         for f1 in self.__dcmp.left_only:
  •             try:
  •                st = os.stat(os.path.join(dir1, f1))
  •             except os.error:
  •                 continue

  •             if stat.S_ISREG(st.st_mode):
  •                 if copyfunc: copyfunc(f1, dir1, dir2)
  •             elif stat.S_ISDIR(st.st_mode):
  •                 fulld1 = os.path.join(dir1, f1)
  •                 fulld2 = os.path.join(dir2, f1)

  •                 if self.__creatdirs:
  •                     try:
  •                         # Copy tree
  •                         print 'Copying tree', fulld2
  •                         shutil.copytree(fulld1, fulld2)
  •                         self.__numnewdirs += 1
  •                         print 'Done.'
  •                     except shutil.Error, e:
  •                         print e
  •                         self.__numdirsfld += 1

  •                         # jump to next file/dir in loop since this op failed
  •                         continue

  •                 # Call tail recursive
  •                 # if os.path.exists(fulld2):
  •                 #    self.__dowork(fulld1, fulld2, copyfunc, updatefunc)

  •         # common files/directories
  •         for f1 in self.__dcmp.common:
  •             try:
  •                 st = os.stat(os.path.join(dir1, f1))
  •             except os.error:
  •                 continue

  •             if stat.S_ISREG(st.st_mode):
  •                 if updatefunc: updatefunc(f1, dir1, dir2)
  •             elif stat.S_ISDIR(st.st_mode):
  •                 fulld1 = os.path.join(dir1, f1)
  •                 fulld2 = os.path.join(dir2, f1)
  •                 # Call tail recursive
  •                 self.__dowork(fulld1, fulld2, copyfunc, updatefunc)


  •     def __copy(self, filename, dir1, dir2):
  •         &quot;&quot;&quot; Private function for copying a file &quot;&quot;&quot;

  •         # NOTE: dir1 is source & dir2 is target
  •         if self.__copyfiles:

  •             print 'Copying file', filename, dir1, dir2
  •             try:
  •                 if self.__copydirection== 0 or self.__copydirection == 2:  # source to target

  •                     if not os.path.exists(dir2):
  •                         if self.__forcecopy:
  •                             os.chmod(os.path.dirname(dir2), 0777)
  •                         try:
  •                             os.makedirs(dir1)
  •                         except OSError, e:
  •                             print e
  •                             self.__numdirsfld += 1

  •                     if self.__forcecopy:
  •                         os.chmod(dir2, 0777)

  •                     sourcefile = os.path.join(dir1, filename)
  •                     try:
  •                         shutil.copy(sourcefile, dir2)
  •                         self.__numfiles += 1
  •                     except (IOError, OSError), e:
  •                         print e
  •                         self.__numcopyfld += 1

  •                 elif self.__copydirection==1 or self.__copydirection == 2: # target to source

  •                     if not os.path.exists(dir1):
  •                         if self.__forcecopy:
  •                             os.chmod(os.path.dirname(dir1), 0777)

  •                         try:
  •                             os.makedirs(dir1)
  •                         except OSError, e:
  •                             print e
  •                             self.__numdirsfld += 1

  •                     targetfile = os.path.abspath(os.path.join(dir1, filename))
  •                     if self.__forcecopy:
  •                         os.chmod(dir1, 0777)

  •                     sourcefile = os.path.join(dir2, filename)

  •                     try:
  •                         shutil.copy(sourcefile, dir1)
  •                         self.__numfiles += 1
  •                     except (IOError, OSError), e:
  •                         print e
  •                         self.__numcopyfld += 1

  •             except Exception, e:
  •                 print 'Error copying  file', filename, e

  •     def __cmptimestamps(self, filest1, filest2):
  •         &quot;&quot;&quot; Compare time stamps of two files and return True
  •         if file1 (source) is more recent than file2 (target) &quot;&quot;&quot;

  •         return ((filest1.st_mtime > filest2.st_mtime) or \
  •                    (not self.__modtimeonly and (filest1.st_ctime > filest2.st_mtime)))

  •     def __update(self, filename, dir1, dir2):
  •         &quot;&quot;&quot; Private function for updating a file based on
  •         last time stamp of modification &quot;&quot;&quot;

  •         print 'Updating file', filename

  •         # NOTE: dir1 is source & dir2 is target
  •         if self.__updatefiles:

  •             file1 = os.path.join(dir1, filename)
  •             file2 = os.path.join(dir2, filename)

  •             try:
  •                 st1 = os.stat(file1)
  •                 st2 = os.stat(file2)
  •             except os.error:
  •                 return -1

  •             # Update will update in both directions depending
  •             # on the timestamp of the file & copy-direction.

  •             if self.__copydirection==0 or self.__copydirection == 2:

  •                 # Update file if file's modification time is older than
  •                 # source file's modification time, or creation time. Sometimes
  •                 # it so happens that a file's creation time is newer than it's
  •                 # modification time! (Seen this on windows)
  •                 if self.__cmptimestamps( st1, st2 ):
  •                     print 'Updating file ', file2 # source to target
  •                     try:
  •                         if self.__forcecopy:
  •                             os.chmod(file2, 0666)

  •                         try:
  •                             shutil.copy(file1, file2)
  •                             self.__numupdates += 1
  •                             return 0
  •                         except (IOError, OSError), e:
  •                             print e
  •                             self.__numupdsfld += 1
  •                             return -1

  •                     except Exception, e:
  •                         print e
  •                         return -1

  •             elif self.__copydirection==1 or self.__copydirection == 2:

  •                 # Update file if file's modification time is older than
  •                 # source file's modification time, or creation time. Sometimes
  •                 # it so happens that a file's creation time is newer than it's
  •                 # modification time! (Seen this on windows)
  •                 if self.__cmptimestamps( st2, st1 ):
  •                     print 'Updating file ', file1 # target to source
  •                     try:
  •                         if self.__forcecopy:
  •                             os.chmod(file1, 0666)

  •                         try:
  •                             shutil.copy(file2, file1)
  •                             self.__numupdates += 1
  •                             return 0
  •                         except (IOError, OSError), e:
  •                             print e
  •                             self.__numupdsfld += 1
  •                             return -1

  •                     except Exception, e:
  •                         print e
  •                         return -1

  •         return -1

  •     def __dirdiffandcopy(self, dir1, dir2):
  •         &quot;&quot;&quot; Private function which does directory diff & copy &quot;&quot;&quot;
  •         self.__dowork(dir1, dir2, self.__copy)

  •     def __dirdiffandupdate(self, dir1, dir2):
  •         &quot;&quot;&quot; Private function which does directory diff & update  &quot;&quot;&quot;
  •         self.__dowork(dir1, dir2, None, self.__update)

  •     def __dirdiffcopyandupdate(self, dir1, dir2):
  •         &quot;&quot;&quot; Private function which does directory diff, copy and update (synchro) &quot;&quot;&quot;
  •         self.__dowork(dir1, dir2, self.__copy, self.__update)

  •     def __dirdiff(self):
  •         &quot;&quot;&quot; Private function which only does directory diff &quot;&quot;&quot;

  •         if self.__dcmp.left_only:
  •             print 'Only in', self.__dir1
  •             for x in self.__dcmp.left_only:
  •                 print '>>', x

  •         if self.__dcmp.right_only:
  •             print 'Only in', self.__dir2
  •             for x in self.__dcmp.right_only:
  •                 print '<<', x

  •         if self.__dcmp.common:
  •             print 'Common to', self.__dir1,' and ',self.__dir2
  •             print
  •             for x in self.__dcmp.common:
  •                 print '--', x
  •         else:
  •             print 'No common files or sub-directories!'

  •     def synchronize(self):
  •         &quot;&quot;&quot; Synchronize will try to synchronize two directories w.r.t
  •         each other's contents, copying files if necessary from source
  •         to target, and creating directories if necessary. If the optional
  •         argument purge is True, directories in target (dir2) that are
  •         not present in the source (dir1) will be deleted . Synchronization
  •         is done in the direction of source to target &quot;&quot;&quot;

  •         self.__copyfiles = True
  •         self.__updatefiles = True
  •         self.__creatdirs = True
  •         self.__copydirection = 0

  •         print 'Synchronizing directory', self.__dir2, 'with', self.__dir1 ,'\n'
  •         self.__dirdiffcopyandupdate(self.__dir1, self.__dir2)

  •     def update(self):
  •         &quot;&quot;&quot; Update will try to update the target directory
  •         w.r.t source directory. Only files that are common
  •         to both directories will be updated, no new files
  •         or directories are created &quot;&quot;&quot;

  •         self.__copyfiles = False
  •         self.__updatefiles = True
  •         self.__purge = False
  •         self.__creatdirs = False

  •         print 'Updating directory', self.__dir2, 'from', self.__dir1 , '\n'
  •         self.__dirdiffandupdate(self.__dir1, self.__dir2)

  •     def dirdiff(self):
  •         &quot;&quot;&quot; Only report difference in content between two
  •         directories &quot;&quot;&quot;

  •         self.__copyfiles = False
  •         self.__updatefiles = False
  •         self.__purge = False
  •         self.__creatdirs = False
  •         self.__updatefiles = False

  •         print 'Difference of directory ', self.__dir2, 'from', self.__dir1 , '\n'
  •         self.__dirdiff()

  •     def report(self):
  •         &quot;&quot;&quot; Print report of work at the end &quot;&quot;&quot;

  •         # We need only the first 4 significant digits
  •         tt = (str(self.__endtime - self.__starttime))[:4]

  •         print '\nPython robocopier finished in',tt, 'seconds.'
  •         print self.__numdirs, 'directories parsed,',self.__numfiles, 'files copied.'
  •         if self.__numdelfiles:
  •             print self.__numdelfiles, 'files were purged.'
  •         if self.__numdeldirs:
  •             print self.__numdeldirs, 'directories were purged.'
  •         if self.__numnewdirs:
  •             print self.__numnewdirs, 'directories were created.'
  •         if self.__numupdates:
  •             print self.__numupdates, 'files were updated by timestamp.'

  •         # Failure stats
  •         print '\n'
  •         if self.__numcopyfld:
  •             print self.__numcopyfld, 'files could not be copied.'
  •         if self.__numdirsfld:
  •             print self.__numdirsfld, 'directories could not be created.'
  •         if self.__numupdsfld:
  •             print self.__numupdsfld, 'files could not be updated.'
  •         if self.__numdeldfld:
  •             print self.__numdeldfld, 'directories could not be purged.'
  •         if self.__numdelffld:
  •             print self.__numdelffld, 'files could not be purged.'

  • if __name__==&quot;__main__&quot;:
  •     import sys

  •     if len(sys.argv)<2:
  •         sys.exit( usage() % PyRobocopier.prog_name )

  •     copier = PyRobocopier()
  •     copier.parse_args(sys.argv[1:])
  •     copier.do_work()

  •     # print report at the end
  •     copier.report()
  

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-548889-1-1.html 上篇帖子: python爬虫学习过程: 下篇帖子: Python开发(基础):初识Python
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表