Python 同步文件夾


將基礎文件夾下的文件,按照目錄結構,同步到目標文件夾下,如果目標文件夾下沒有相應的目錄結構,就創建目錄,然后再將基礎文件夾下的文件同步到相應的目錄下去。

 

import os
import shutil
import time
import hashlib

# MD5值
def getMD5(path):
    f=open(path,'rb')
    d5 = hashlib.md5()      #生成一個hash的對象
    with open(path,'rb') as f:
        while True:
            content = f.read(40960)
            if not content:
                break
            d5.update(content)   # 每次讀取一部分,然后添加到hash對象里
    # print('MD5 : %s' % d5.hexdigest())
    return d5.hexdigest()        # 打印16進制的hash值

# 裝飾器,計時用的
def timer(func):   # 高階函數:以函數作為參數
    def deco(*args,**kwargs):    # 嵌套函數,在函數內部以 def 聲明一個函數,接受 被裝飾函數的所有參數
        time1 = time.time()
        func(*args,**kwargs)
        time2 = time.time()
        print('Elapsed %ss\n' % round(time2-time1,2))
    return deco    # 注意,返回的函數沒有加括號!所以返回的是一個內存地址,而不是函數的返回值

@timer
def compare(baseFolder,targetFolder,content_compare='y'):
    '''
    :param baseFolder:   基礎文件夾,將基礎文件夾中的文件按照相應的目錄結構同步到目標文件夾中。
    :param targetFolder: 目標文件夾
    :content_compare: 是否比對兩個文件的內容,默認比對,防止文件內容有更改。參數值如果不是'y',則不比對內容,只判斷目標文件夾是否有同名文件,有就跳過,沒有就復制過去。
    '''
    n = 0
    for path,subpath,files in os.walk(baseFolder):
        for file in files:
            # 獲取文件的絕對路徑
            absPath = os.path.join(path,file)
            # 文件的后半截路徑,即文件的相對路徑
            file_path = absPath.replace(baseFolder,'')
            # 去掉路徑前面的\
            if file_path[:1] == '\\':
                file_path = file_path[1:]

            # 替換目錄末尾的\
            if targetFolder[:1] == '\\':
                targetFolder = targetFolder[1:]

            # 判斷目標文件夾是否有相應的文件
            filePath = os.path.join(targetFolder,file_path)
            
            # 創建文件夾路徑
            fileFolder = os.path.dirname(filePath)
            
            # 如果目標文件夾不存在此文件
            if not os.path.exists(filePath):
                os.makedirs(fileFolder,exist_ok=True)
                # 復制文件
                shutil.copy(absPath,fileFolder)
                print(f'\n     {absPath}   -------------->   {filePath}')
            else: # 如果目標文件夾已經存在某文件
                # 如果要對比兩個文件的內容
                if content_compare == 'y':
                    # 先對比兩個文件的修改時間(誰的時間越大,代表誰的內容越新)
                    baseTime = os.stat(absPath).st_mtime
                    targetTime = os.stat(filePath).st_mtime
                    if baseTime-targetTime > 0:
                        # 比了時間,再比一下MD5。如果MD5也不同,就將這個時間最新的文件復制過去
                        baseMD5 = getMD5(absPath)
                        targetMD5 = getMD5(filePath)
                        if baseMD5 != targetMD5:
                            os.unlink(filePath)
                            shutil.copy(absPath,fileFolder)
                            print(f'\n     {absPath}   -------------->   {filePath}')
                        else:
                            # MD5相同,而目標文件夾中的時間又小,就將修改時間改大,防止下次運行此腳本時再對比一遍MD5,浪費時間
                            # 修改文件的訪問和修改時間,改成當前系統時間
                            os.utime(filePath)
            n+=1
            print("\r%s:  Has scanned %s files. "%(baseFolder,n),end='' )

if __name__ == '__main__':
    print('----------Copying the files of BaseFolder to TargetFolder.----------\n')
    base = input('Input base folder:')
    target = input('Input target folder:')
    # 當有相同文件時,是否對比文件內容,把最新的同步過去,適用於經常變動的文件,如腳本,文檔
    content_compare = input('Compare content? y/n: ').lower()
    if base == '':
        compare(r'D:\備份',r'G:\備份')
        compare(r'D:\software',r'G:\software')
        compare(r'E:\文檔',r'G:\document')
    else:
        compare(base,target,content_compare)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM