Files
MoFin/archive/20260722-scripts-cleanup/audit_duplication.py
T

84 lines
2.7 KiB
Python

#!/usr/bin/env python3
"""audit_duplication.py — 扫描 MoFin 相关目录的文件重复情况"""
import os, hashlib, json
from collections import defaultdict
LOCATIONS = [
'/home/hmo/MoFin',
'/home/hmo/MoFin/scripts',
'/home/hmo/MoFin/deploy/profile-scripts',
'/home/hmo/MoFin/deploy/bot',
'/home/hmo/.hermes/profiles/position-analyst/scripts',
'/home/hmo/.hermes/scripts',
'/home/hmo/web-dashboard',
]
def md5(p):
try:
with open(p, 'rb') as f:
return hashlib.md5(f.read()).hexdigest()[:10]
except Exception:
return 'ERR'
def ino(p):
try:
return os.stat(p).st_ino
except Exception:
return 0
# 收集所有 .py 文件
files = defaultdict(list) # name -> [(loc, path, md5, inode, is_link)]
for loc in LOCATIONS:
if not os.path.isdir(loc):
continue
for f in os.listdir(loc):
if not f.endswith('.py'):
continue
p = os.path.join(loc, f)
if not os.path.isfile(p):
continue
files[f].append({
'loc': loc, 'path': p, 'md5': md5(p), 'inode': ino(p),
'is_link': os.path.islink(p),
'size': os.path.getsize(p),
'mtime': int(os.path.getmtime(p)),
})
print("=== 重复文件(同名出现在2+位置)===")
dups = {k: v for k, v in files.items() if len(v) > 1}
identical = 0
hardlinked = 0
diverged = 0
for name in sorted(dups):
entries = dups[name]
md5s = set(e['md5'] for e in entries)
inodes = set(e['inode'] for e in entries)
if len(inodes) == 1:
status = 'HARDLINK(同一文件)'
hardlinked += 1
elif len(md5s) == 1:
status = 'COPY(内容相同,多份独立)'
identical += 1
else:
status = 'DIVERGED(内容不同!)'
diverged += 1
print(f"{status} {name}")
for e in entries:
print(f" {e['path']} md5={e['md5']} ino={e['inode']} size={e['size']}")
print(f"\n汇总: {len(dups)} 个重复文件名 | hardlink={hardlinked} 内容相同副本={identical} 内容分叉={diverged}")
print("\n=== deploy/profile-scripts 中有但 position-analyst/scripts 中缺失的 ===")
pa_dir = '/home/hmo/.hermes/profiles/position-analyst/scripts'
deploy_dir = '/home/hmo/MoFin/deploy/profile-scripts'
pa_files = set(os.listdir(pa_dir)) if os.path.isdir(pa_dir) else set()
for f in sorted(os.listdir(deploy_dir)):
if f.endswith('.py') and f not in pa_files:
print(f" {f}")
print("\n=== position-analyst/scripts 中有但 deploy 中没有的(可能孤儿)===")
deploy_files = set(os.listdir(deploy_dir))
for f in sorted(pa_files):
if f.endswith('.py') and f not in deploy_files:
p = os.path.join(pa_dir, f)
print(f" {f} size={os.path.getsize(p)}")