まず、シナリオが説明します
1、あまりにも多くのディスクファイル、彼らは、単に重複したファイルを一掃したい、あまりにも面倒なマニュアルを削除するには耐えることができませんでした
2、完成した製品をダウンロードしてください。
Baiduのクラウド:https://pan.baidu.com/s/1W3pHU-dGi_mrd8M140Vogg
抽出コード:ji0r
3、最終用途:
(1)repeat.exeフォルダにファイルを横断するように配置します。
(2)ダブルクリック repeat.exe。
(3)自動的に「指紋」情報記録ファイルを読み取るための1つにより、現在のすべてのフォルダおよびサブフォルダいずれかを横断 /RESULT/md5.hisを、複数行の同一の「フィンガープリント」はパス情報がされるファイルフォームで書かれ /RESULT/record.log 。
(4)カットするために、他の「コピー」しながら、元のファイルのほとんどを保持 /結果/ REPEATS /削除するかどうかを選択するユーザーのための準備ができて、フォルダを。
深トラバーサル(5)より、「カトン」であってもよい早期横断中に第1、ファイルを大量に検索するファイル。
大きなファイルに直面したとき(6)、状況を横断し、あまりにも多くの時間を要し、あなたが直接プログラムを閉じることができ、次回は、ファイルを介して横断効率を向上させ、無駄な労力を削減トラバース、トラバースを繰り返されることはありません。注:ファイルは削除しないでください /RESULT/md5.hisを 。
実行する前に:
観察/ルート/son.jpg及び /ルート/サブ/son.jpg互いに繰り返します
/ルート/grand.jpg及び /ルート/プロモーター/日/grand.jpg相互に繰り返し
/ルートは/root.jpgない何の繰り返しを
(説明と区別の便宜上、フォルダの下のファイルのすべてのコピーの名前が変更されていない他のファイルに保存されています)
ランタイム:
実行した後:
結果は/ルート/son.jpgのコピー /ルート/サブ/son.jpg
/ルート/grand.jpgコピー /ルート/子/日の/grand.jpgは に移動さ/ルート/結果/ REPEATS /フォルダ
ユーザーは、これらのファイルのコピーを削除するかどうかを選択できます
第二に、需要分析
同じファイルが存在する可能性が繰り返し、ファイル名が同じであってもよい、(「(2)XX」、最古の作成日時、ファイル名ではなく、「コピー」以外の)彼らは、元のファイルを保存したい、異なる場合があります
同じファイルの2つのファイルかどうかを判断するには?どのように正確に区別し、指紋などの身体を特定するには?
ファイルが多すぎ、単一のファイルには、どのように二次的に横断する際に横断最後の結果を再利用するために、あまりにも多くの時間を要するトラバースには大きすぎますか?
特定のファイルのパーミッションを回避するために、どのように全体の横断への影響の欠如?
プログラム・キャッシュ・ゴミを実行するには?
第三に、コードの実装
1、folder.py
# !/usr/bin/python3
# coding: utf-8
import os
import tool
def deep_list(path):
if not os.path.isdir(path):
return list()
try:
fs = os.listdir(path)
except PermissionError:
print("PermissionError:", path)
return list()
info = list()
for f in fs:
fp = tool.join(path, f)
if os.path.isfile(fp):
info.append(fp)
elif os.path.isdir(fp):
info.extend(deep_list(fp))
return info
2、file.py
# !/usr/bin/python3
# coding: utf-8
import hashlib
import os
import traceback
def md5(path):
if not os.path.isfile(path):
return None
try:
hashes = hashlib.md5()
f = open(path, "rb")
while True:
b = f.read(1024)
if not b:
break
hashes.update(b)
f.close()
md = hashes.hexdigest()
print("%s : %s" % (path, md))
return md
except:
traceback.print_exc()
return None
def name_order(path):
if not os.path.exists(path):
return None
path = str(path).lower().strip()
info = os.stat(path)
create = info.st_ctime_ns
if info.st_atime_ns < create:
create = info.st_atime_ns
if info.st_mtime_ns < create:
create = info.st_mtime_ns
suf = os.path.splitext(path)[1]
basename = os.path.basename(path)
name = basename.replace(suf, "").strip()
name = name.replace("(", "(")
name = name.replace(")", ")")
layer = len(path.split("\\"))
return "_".join((suf, str(create), name, str(layer)))
3、tool.py
# !/usr/bin/python3
# coding: utf-8
def join(path, *paths):
path = fmt(path)
for p in paths:
p = fmt(p)
path += "\\" + p
path = fmt(path)
return path
def fmt(path):
if path is None:
return ""
path = path.strip()
while path.find("/") >= 0:
path = path.replace("/", "\\")
while path.find("\\\\") >= 0:
path = path.replace("\\\\", "\\")
return path
4、mei.py
# !/usr/bin/python3
# coding: utf-8
import os
import re
import sys
import tool
def IS_MEI(basename):
return re.match("^_MEI\d+$", basename) and True or False
def remove():
for index, path in enumerate(sys.path):
basename = os.path.basename(path)
if not IS_MEI(basename):
continue
drive = os.path.splitdrive(path)[0]
if "" == drive:
path = tool.join(os.getcwd(), path)
if os.path.isdir(path):
try:
print("remove", path)
os.remove(path)
finally:
break
5、repeat.py(コア)
# !/usr/bin/python3
# coding: utf-8
import gc
import os
import sys
import time
import traceback
this = os.path.abspath(os.path.dirname(__file__))
module = os.path.split(this)[0]
sys.path.append(module)
for i, val in enumerate(sys.path):
print("[%s] %s" % (i + 1, val))
import file
import folder
import tool
import mei
SEGMENTER = ">>"
FOLDER_FOR_RESULT = "RESULT"
FOLDER_FOR_REPEATS = "REPEATS"
FILE_MD5_HIS = "md5.his"
FILE_MD5_TMP = "md5.tmp"
FILE_RECORD_LOG = "record.log"
def read_md5_his(cwd):
his_path = tool.join(cwd, FOLDER_FOR_RESULT, FILE_MD5_HIS)
if not os.path.exists(his_path):
return dict()
with open(his_path, 'r', encoding='utf-8') as f:
lines = f.readlines()
fpMd5 = dict()
for line in lines:
row = line.split(SEGMENTER)
fp = row[0].strip()
md5 = row[1].strip()
if os.path.exists(fp) and len(md5) > 1:
fpMd5[fp] = md5
return fpMd5
def reverse_file_md5(fileMd5):
ls = list()
for fp, md5 in fileMd5.items():
ls.append((fp, md5))
ls.sort(key=lambda ele: ele[1])
md5Fp = dict()
for kv in ls:
fp = kv[0]
md5 = kv[1]
if md5 not in md5Fp:
fps = set()
else:
fps = md5Fp[md5]
fps.add(fp)
md5Fp[md5] = fps
return md5Fp
def scan_folder(cwd):
# step0: listdir
fps = folder.deep_list(cwd)
if len(fps) < 2: # must have it self
print("No FILE IN", cwd)
return
# step1: remove self and root_folder
self = os.path.abspath(sys.executable)
print("SELF IS", self)
if self in fps:
fps.remove(self)
result_path = tool.join(cwd, FOLDER_FOR_RESULT)
for index in range(len(fps) - 1, -1, -1):
fp = fps[index]
if str(fp).startswith(result_path):
fps.remove(fp)
if len(fps) < 1:
print("No FILE IN", cwd)
return
# step2: read history and write to tmp
tmp_path = tool.join(cwd, FOLDER_FOR_RESULT, FILE_MD5_TMP)
fpMd5 = read_md5_his(cwd)
if len(fpMd5) > 0:
rows = ""
for p, md5 in fpMd5.items():
rows += p + SEGMENTER + md5 + "\n"
with open(tmp_path, 'w', encoding='utf-8') as f:
f.write(rows)
print()
# step3: makedir
repeats_path = tool.join(cwd, FOLDER_FOR_RESULT, FOLDER_FOR_REPEATS)
if not os.path.exists(repeats_path):
os.makedirs(repeats_path)
fps = list(fps)
fps.sort(key=lambda fp: os.stat(fp).st_size, reverse=True)
# step4: read file's md5 and append to tmp
tmpMd5 = dict()
for index in range(len(fps)):
fp = fps[index]
if fp in fpMd5:
continue
md5 = file.md5(fp)
if md5 is not None:
tmpMd5[fp] = md5
fpMd5[fp] = md5
if 10 == len(tmpMd5) or (index == len(fps) - 1):
rows = ""
for p, md in tmpMd5.items():
rows += p + SEGMENTER + md + "\n"
with open(tmp_path, 'a', encoding='utf-8') as f:
f.write(rows)
tmpMd5.clear()
print()
# step5: remove the repeat
content = ""
md5Fp = reverse_file_md5(fpMd5)
for md5, fps in md5Fp.items():
if len(fps) < 2:
continue
fps = list(fps)
fps.sort(key=lambda fp: file.name_order(fp))
print("%s : %s" % (md5, ','.join(fps)))
content += ','.join(fps) + "\n"
for i in range(len(fps)):
if i == 0:
# not move the first
continue
old = fps[i]
fn = os.path.basename(old)
new = tool.join(repeats_path, fn)
if old == new:
continue
# if the new is exist
if os.path.exists(new):
try:
os.remove(new)
except:
traceback.print_exc()
# move the repeats to REPEAT/FILES folder
try:
os.rename(old, new)
except:
traceback.print_exc()
# step6: record the repeat
if "" == content:
print("No REPEAT FILE EXISTS")
else:
this_time = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))
record = tool.join(cwd, FOLDER_FOR_RESULT, FILE_RECORD_LOG)
with open(record, 'a', encoding='utf-8') as f:
f.write("\n\n" + this_time + "\n" + content)
def save_file_md5(cwd):
# step7: update md5 history record file
try:
his_path = tool.join(cwd, FOLDER_FOR_RESULT, FILE_MD5_HIS)
tmp_path = tool.join(cwd, FOLDER_FOR_RESULT, FILE_MD5_TMP)
if os.path.exists(tmp_path):
if os.path.exists(his_path):
os.remove(his_path)
os.rename(tmp_path, his_path)
except:
traceback.print_exc()
if __name__ == '__main__':
try:
cwd = os.getcwd()
print("\nCURRENT PATH IS %s\n" % cwd)
scan_folder(cwd)
except:
traceback.print_exc()
finally:
save_file_md5(cwd)
gc.collect()
input("\nPRESS ANY KEYS TO EXIT\n")
mei.remove()
第四に、パッケージexeファイル
pyinstaller -F repeat.py
部門は、詳細は、詳細を参照してくださいことはありません。