最近在備份手機上的照片的時候,純手工操作覺得有些麻煩,就想寫個指令碼自動進行。因為備份的時候有些照片以前備份過了,所以需要有個判重操作。
主要功能在copyFiles()函式裡實現,如下:
def copyFiles(src, dst): srcFiles = os.listdir(src) dstFiles = dict(map(lambda x:[x, ''], os.listdir(dst))) filesCopiedNum = 0 # 對原始檔夾中的每個檔案若不存在於目的資料夾則複製 for file in srcFiles: src_path = os.path.join(src, file) dst_path = os.path.join(dst, file) # 若源路徑為資料夾,若存在於目標資料夾,則遞迴呼叫本函式;否則先建立再遞迴。 if os.path.isdir(src_path): if not os.path.isdir(dst_path): os.makedirs(dst_path) filesCopiedNum += copyFiles(src_path, dst_path) # 若源路徑為檔案,不重複則複製,否則無操作。 elif os.path.isfile(src_path): if not dstFiles.has_key(file): shutil.copyfile(src_path, dst_path) filesCopiedNum += 1 return filesCopiedNum
這裡我首先使用os.listdir()函式來遍歷原始檔夾src和目標資料夾dst,得到兩個檔案列表,但由於我需要判重操作,因此需要在dst檔案列表中進行查詢操作。由於列表的查詢效率不高,而字典是一個雜湊表,查詢效率較高,因此我將目標檔案列表轉換成一個只有鍵沒有值的字典:
dstFiles = dict(map(lambda x:[x, ''], os.listdir(dst)))
然後我遍歷原始檔列表,若該路徑是一個資料夾,先判斷該資料夾在目標路徑中是否存在,若不存在,則先建立一個新路徑。然後遞迴呼叫本函式。其實不存在的時候更高效的方法是呼叫shutil.copytree()函式,但由於此處需要計算拷貝的檔案數量,因此就沒有呼叫該函式。
若該路徑是一個檔案,則首先判斷該檔案在目標資料夾中是否存在。若不存在,則拷貝。
由於寫這個指令碼主要是為了同步手機相簿到PC,因此只簡單地判斷一下檔名。若要判斷不同名但相同的檔案,則可以繼續判斷一下md5值,這裡就不再贅述。
#!/usr/bin/env python # -*- coding: UTF-8 -*- # 輸入兩個資料夾a和b路徑,將a中的檔案拷進b,並計算拷貝的檔案數。重複的不作處理。 # pythontab.com 2013-07-19 import os import shutil def copyFiles(src, dst): srcFiles = os.listdir(src) dstFiles = dict(map(lambda x:[x, ''], os.listdir(dst))) filesCopiedNum = 0 # 對原始檔夾中的每個檔案若不存在於目的資料夾則複製 for file in srcFiles: src_path = os.path.join(src, file) dst_path = os.path.join(dst, file) # 若源路徑為資料夾,若存在於目標資料夾,則遞迴呼叫本函式;否則先建立再遞迴。 if os.path.isdir(src_path): if not os.path.isdir(dst_path): os.makedirs(dst_path) filesCopiedNum += copyFiles(src_path, dst_path) # 若源路徑為檔案,不重複則複製,否則無操作。 elif os.path.isfile(src_path): if not dstFiles.has_key(file): shutil.copyfile(src_path, dst_path) filesCopiedNum += 1 return filesCopiedNum def test(): src_dir = os.path.abspath(raw_input('Please enter the source path: ')) if not os.path.isdir(src_dir): print 'Error: source folder does not exist!' return 0 dst_dir = os.path.abspath(raw_input('Please enter the destination path: ')) if os.path.isdir(dst_dir): num = copyFiles(src_dir, dst_dir) else: print 'Destination folder does not exist, a new one will be created.' os.makedirs(dst_dir) num = copyFiles(src_dir, dst_dir) print 'Copy complete:', num, 'files copied.' if __name__ == '__main__': test()