本文目录导读:

我来介绍几种检测重复文件夹的方法,包括不同的实现方案:
基于文件内容哈希的精确检测
Python 实现
import os
import hashlib
from collections import defaultdict
def get_folder_hash(folder_path):
"""计算文件夹的哈希值(基于所有文件内容)"""
sha256_hash = hashlib.sha256()
# 遍历所有文件(按排序保持一致性)
for root, dirs, files in os.walk(folder_path):
dirs.sort()
files.sort()
for file_name in files:
file_path = os.path.join(root, file_name)
# 添加相对路径信息
rel_path = os.path.relpath(file_path, folder_path)
sha256_hash.update(rel_path.encode())
# 添加文件内容
with open(file_path, "rb") as f:
for chunk in iter(lambda: f.read(4096), b""):
sha256_hash.update(chunk)
return sha256_hash.hexdigest()
def find_duplicate_folders(root_path):
"""查找重复文件夹"""
folder_hashes = defaultdict(list)
# 遍历所有子文件夹
for item in os.listdir(root_path):
item_path = os.path.join(root_path, item)
if os.path.isdir(item_path):
try:
folder_hash = get_folder_hash(item_path)
folder_hashes[folder_hash].append(item_path)
except Exception as e:
print(f"Error processing {item_path}: {e}")
# 返回重复的文件夹
duplicates = {hash_val: paths for hash_val, paths in folder_hashes.items()
if len(paths) > 1}
return duplicates
# 使用示例
root = "/path/to/search"
duplicates = find_duplicate_folders(root)
for hash_val, paths in duplicates.items():
print(f"Duplicate folders ({len(paths)} copies):")
for path in paths:
print(f" - {path}")
基于文件元数据的快速检测
import os
from collections import defaultdict
def get_folder_signature(folder_path):
"""快速获取文件夹特征(文件数量、大小等)"""
total_files = 0
total_size = 0
structure = []
for root, dirs, files in os.walk(folder_path):
dirs.sort()
files.sort()
# 记录相对路径结构
rel_path = os.path.relpath(root, folder_path)
structure.append({
'path': rel_path,
'files': files,
'dirs': dirs
})
total_files += len(files)
for file_name in files:
file_path = os.path.join(root, file_name)
try:
total_size += os.path.getsize(file_path)
except:
pass
return {
'total_files': total_files,
'total_size': total_size,
'structure_hash': hash(str(structure))
}
def find_duplicate_folders_fast(root_path):
"""快速查找可能的重复文件夹"""
folder_signatures = defaultdict(list)
for item in os.listdir(root_path):
item_path = os.path.join(root_path, item)
if os.path.isdir(item_path):
sig = get_folder_signature(item_path)
folder_signatures[sig['structure_hash']].append(item_path)
# 只返回可能的重复项
potential_dupes = {k: v for k, v in folder_signatures.items() if len(v) > 1}
return potential_dupes
Shell 脚本检测
#!/bin/bash
# 基于文件列表的重复检测
function find_duplicate_dirs() {
local search_path="$1"
# 获取所有子目录的文件列表
for dir in "$search_path"/*/; do
if [ -d "$dir" ]; then
dir_name=$(basename "$dir")
# 生成文件列表(排序后)
file_list=$(find "$dir" -type f -exec basename {} \; | sort | md5sum)
# 使用关联数组存储
echo "$dir_name|$file_list"
fi
done | sort -t'|' -k2 | awk -F'|' '
{
if ($2 == prev_hash) {
print "DUPLICATE: " prev_dir " <=> " $1
} else {
prev_hash = $2
prev_dir = $1
}
}
'
}
# 使用示例
find_duplicate_dirs "/path/to/check"
使用 fdupes 工具(快速)
import subprocess
import json
def find_duplicates_with_fdupes(directory, recurse=True):
"""使用 fdupes 工具检测重复文件,然后分析文件夹"""
cmd = ['fdupes', '-r', '-S', directory]
result = subprocess.run(cmd, capture_output=True, text=True)
# 解析输出,分组重复文件
duplicate_groups = []
current_group = []
for line in result.stdout.split('\n'):
if line.strip() == '':
if current_group:
duplicate_groups.append(current_group)
current_group = []
else:
current_group.append(line.strip())
# 分析哪些文件夹包含重复文件
folder_duplicates = defaultdict(set)
for group in duplicate_groups:
if len(group) > 1:
for file_path in group:
folder = os.path.dirname(file_path)
# 记录重复文件对
for other_file in group:
if other_file != file_path:
folder_duplicates[folder].add(other_file)
return folder_duplicates
Windows PowerShell 脚本
# 查找重复文件夹的PowerShell脚本
function Find-DuplicateFolders {
param(
[string]$Path,
[switch]$Recurse
)
$folderHashes = @{}
# 获取所有子文件夹
$folders = Get-ChildItem -Path $Path -Directory -Recurse:$Recurse
foreach ($folder in $folders) {
$hash = New-Object System.Security.Cryptography.SHA256Managed
# 获取文件夹中所有文件
$files = Get-ChildItem -Path $folder.FullName -File -Recurse | Sort-Object Name
foreach ($file in $files) {
$stream = [System.IO.File]::OpenRead($file.FullName)
$hash.ComputeHash($stream) | Out-Null
$stream.Close()
}
$hashString = [System.BitConverter]::ToString($hash.Hash) -replace '-', ''
if (-not $folderHashes.ContainsKey($hashString)) {
$folderHashes[$hashString] = @()
}
$folderHashes[$hashString] += $folder.FullName
}
# 只返回重复项
$folderHashes.GetEnumerator() | Where-Object { $_.Value.Count -gt 1 }
}
# 使用示例
Find-DuplicateFolders -Path "C:\MyFolder" -Recurse
性能优化版本
import os
import hashlib
from concurrent.futures import ThreadPoolExecutor, as_completed
def hash_file_quick(file_path):
"""快速哈希单个文件"""
h = hashlib.md5()
with open(file_path, 'rb') as f:
# 只读取前4KB和最后4KB作为快速比较
first_chunk = f.read(4096)
h.update(first_chunk)
f.seek(-4096, 2)
last_chunk = f.read(4096)
h.update(last_chunk)
return h.hexdigest()
def compare_folders_parallel(folder1, folder2):
"""并行比较两个文件夹"""
def get_files_structure(path):
"""获取文件结构"""
files = []
for root, dirs, fnames in os.walk(path):
for fname in fnames:
fpath = os.path.join(root, fname)
rel_path = os.path.relpath(fpath, path)
files.append((rel_path, fpath))
return sorted(files, key=lambda x: x[0])
files1 = get_files_structure(folder1)
files2 = get_files_structure(folder2)
# 快速大小和数量检查
if len(files1) != len(files2):
return False
# 并行哈希比较
with ThreadPoolExecutor(max_workers=4) as executor:
futures = []
for i, ((rel1, path1), (rel2, path2)) in enumerate(zip(files1, files2)):
if rel1 != rel2:
return False
futures.append(executor.submit(hash_file_quick, path1))
futures.append(executor.submit(hash_file_quick, path2))
# 验证哈希
hashes = []
for future in as_completed(futures):
hashes.append(future.result())
# 分组比较
for i in range(0, len(hashes), 2):
if hashes[i] != hashes[i+1]:
return False
return True
使用建议
-
选择合适的方法:
- 精确检测:使用完整的文件哈希
- 快速检测:使用文件数量和大小
- 大规模检测:使用并行处理
-
性能优化:
- 先比较文件数量和总大小
- 使用快速哈希(MD5而非SHA256)
- 只读取部分文件内容
-
注意事项:
- 处理权限问题
- 考虑符号链接
- 排除系统文件
- 处理大文件时的内存管理
根据具体需求选择合适的实现方案即可。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播