-- 系列:日常辦公技巧
-- 作者:alex tang
-- 時間:01/21-2019
一、業(yè)務(wù)背景
1.1背景簡介
幾年的咨詢工作不僅讓我變得更有經(jīng)驗,更養(yǎng)成了我松鼠黨的習慣。堆積的資料越來越多,而且重復(fù)的文件被放在了不同的目錄,占用的空間越來越大,數(shù)量也多得已經(jīng)不太適合人工分辨整理。尤其是有的一模一樣的文件被改成不一樣的名字,但實質(zhì)相同。這種壞現(xiàn)象不僅是電腦,連云盤也是如此。
前兩天整理自己的網(wǎng)盤時發(fā)現(xiàn)空間已滿,想要使用使用其文件去重功能居然要開通會員,最低一檔需付費30大洋。作為科技宅遂決定不讓自己的python吃灰了,自己寫著玩玩。
本文會和大家分享如何實現(xiàn)文件去重,如何掃描自己硬盤和網(wǎng)盤的每一個目錄。
1.2知識點預(yù)告
本文完成過程中將使用:
- MD5原理
- 遍歷文件夾
- pathlib模塊的使用
- logging模塊的使用
1.3使用環(huán)境
python=3.6.7
pathlib=2.3.2
二、實現(xiàn)原理
在開始之前,我先解釋一下這些代碼運行的原理——基于文件的完整性( integrity)。如果兩個文件的內(nèi)容相同,不管它們文件名相同與否,它們的MD5值(或者其他哈希算法值)必定是相同的。在這篇文章里,我使用MD5值來判斷文件的完整性。
三、開發(fā)準備
linux打開終端,windows使用win+r打開cmd命令行。進入code目錄,創(chuàng)建work文件夾,將其作為工作目錄。
! cd C:\test\Code&&mkdir work&&cd work
子目錄或文件 work 已經(jīng)存在。
為了實驗,我在該文件夾下面放了一個文件,并復(fù)制了一下。這樣兩個文件的名字就不相同了。
安裝所需模塊
! pip install hashlib
! pip install logging
! pip install pathlib
四、開發(fā)步驟
4.1導(dǎo)入所需package
import os
import hashlib
import logging
import sys
from pathlib import Path
4.2編寫日志函數(shù)
指定logger輸出格式,明確日志文件名稱和存儲位置,制定日志的最低輸出級別。
def logger():
""" 獲取logger"""
logger = logging.getLogger()
if not logger.handlers:
# 指定logger輸出格式
formatter = logging.Formatter('%(asctime)s %(levelname)-8s: %(message)s')
# 文件日志
file_handler = logging.FileHandler("test.log")
file_handler.setFormatter(formatter) # 可以通過setFormatter指定輸出格式
# 控制臺日志
console_handler = logging.StreamHandler(sys.stdout)
console_handler.formatter = formatter # 也可以直接給formatter賦值
# 為logger添加的日志處理器
logger.addHandler(file_handler)
logger.addHandler(console_handler)
# 指定日志的最低輸出級別,默認為WARN級別
logger.setLevel(logging.INFO)
return logger
4.3獲得文件的唯一標識 - MD5值
假如你要處理的重復(fù)文件有不同的文件名,最簡單的辦法就是通過MD5來確定兩個文件是不是一樣的。
def md5sum(filename, blocksize=65536):
hash = hashlib.md5()
with open(filename, "rb") as f:
for block in iter(lambda: f.read(blocksize), b""):
hash.update(block)
return hash.hexdigest()
這個方法可以快速獲得一個文件的MD5值,blocksize 可以根據(jù)文件大小和CPU性能調(diào)整,一般選擇的值約等于文件的平均大小。
4.4保存所有文件標識和路徑
接下來遍歷所有文件,使用MD5作為key,路徑作為value,保存起來。
dup = {}
def build_hash_dict(dir_path, pattern='*.xlsx'):
def save(file):
hash = md5sum(file)
if hash not in dup.keys():
dup[hash] = [file]
else:
dup[hash].append(file)
p = Path(dir_path)
for item in p.glob('**/' + pattern):
save(str(item))
4.5處理重復(fù)文件
最后一步非常簡單,把上一步建立的字典做一個簡單的過濾就能找到重復(fù)文件。
def main():
log = logger()
def get_duplicate():
return {k: v for k, v in dup.items() if len(v) > 1}
build_hash_dict(work_path)
for hash, files in get_duplicate().items():
log.info("{}: {}".format(hash, files))
如果你想直接刪除冗余文件,而不是自己來判斷從哪個文件里面刪除,可在記錄日志后遍歷日志文件列表,刪除指定文件之外的其他文件內(nèi)容。
#import os
#[os.remove(file) for file in files[1:]]
4.6某度網(wǎng)盤查重
原理是一樣的,某度網(wǎng)盤在Windows上安裝后會生成本地數(shù)據(jù)庫,經(jīng)測試是sqlite的,簡直和python不要太友好。我們直接訪問Windows下的百度網(wǎng)盤數(shù)據(jù)庫,通過判斷文件的MD5碼就可以進行去重。就不上代碼了,如果大家需要可以留言聯(lián)系我索取。
執(zhí)行過程中不需要登錄你的百度網(wǎng)盤賬號,你也就不用怕賬號被盜了吧。
4.7執(zhí)行函數(shù)代碼
if __name__ == '__main__':
dup = {}
work_path = 'C:\\test\\Code\\work'
main()
2019-01-20 19:37:43,267 INFO : bea3107f0ef871594bedcd992265ade4: ['C:\\test\\Code\\work\\abtForCustomValue-2 - 副本 - 副本.xlsx', 'C:\\test\\Code\\work\\abtForCustomValue-2 - 副本.xlsx']
五、代碼獲取
如果您想獲得完整代碼或者封裝好的exe程序,可以給我留言。如果你有建議或者想法,也歡迎留言與我溝通。