我想写一个关于 bash 的算法,它可以找到重复的文件
如何添加尺寸选项?
find . -not -empty -type f -printf "%s\n" | sort -rn | uniq -d |\
xargs -I{} -n1 find . -type f -size {}c -print0 | xargs -0 md5sum |\
sort | uniq -w32 --all-repeated=separate
这就是你想要的方式。此代码首先根据大小定位 dup,然后是 MD5 哈希。请注意与-size
您的问题相关的 , 的使用。享受。假设您要在当前目录中搜索。如果没有,请将 更改find .
为适合您要搜索的目录。
find /path/to/folder1 /path/to/folder2 -type f -printf "%f %s\n" | sort | uniq -d
find 命令在两个文件夹中查找文件,仅打印文件名(剥离前导目录)和大小,仅排序和显示重复项。这确实假设文件名中没有换行符。
这可能是一个迟到的答案,但现在有更快的替代方案fdupes
。
我有时间做了一个小测试。对于一个包含 54,000 个文件、总大小为 17G 的文件夹,在标准 (8 vCPU/30G) Google 虚拟机上:
fdupes
耗时 2m 47.082sfindup
耗时 13.556 秒jdupes
耗时 0.165s但是,我的经验是,如果您的文件夹太大,时间可能会变得很长(数小时,如果不是数天),因为成对比较(或充其量排序)和极度消耗内存的操作很快就会变得难以忍受。在整个磁盘上运行这样的任务是不可能的。
通常我使用fdupes -r -S .
. 但是当我搜索较少数量的非常大文件的副本时,fdupes
需要很长时间才能完成,因为它会对整个文件进行完整的校验和(我猜)。
我通过只比较前 1 兆字节来避免这种情况。它不是超级安全的,如果你想 100% 确定,你必须检查它是否真的是重复的。但是两个不同的视频(我的情况)具有相同的 1 兆字节但不同的进一步内容的可能性是相当理论上的。
所以我写了这个脚本。它为加快速度所做的另一个技巧是将特定路径的结果哈希存储到文件中。我依赖于文件不会更改的事实。
我将此代码粘贴到控制台而不是运行它 - 为此,它需要更多的工作,但在这里你有一个想法:
find -type f -size +3M -print0 | while IFS= read -r -d '' i; do
echo -n '.'
if grep -q "$i" md5-partial.txt; then
echo -n ':'; #-e "\n$i ---- Already counted, skipping.";
continue;
fi
MD5=`dd bs=1M count=1 if="$i" status=none | md5sum`
MD5=`echo $MD5 | cut -d' ' -f1`
if grep "$MD5" md5-partial.txt; then echo -e "Duplicate: $i"; fi
echo $MD5 $i >> md5-partial.txt
done
fi
## Show the duplicates
#sort md5-partial.txt | uniq --check-chars=32 -d -c | sort -b -n | cut -c 9-40 | xargs -I '{}' sh -c "grep '{}' md5-partial.txt && echo"
另一个用于确定最大重复文件的 bash 片段:
## Show wasted space
if [ false ] ; then
sort md5-partial.txt | uniq --check-chars=32 -d -c | while IFS= read -r -d '' LINE; do
HASH=`echo $LINE | cut -c 9-40`;
PATH=`echo $LINE | cut -c 41-`;
ls -l '$PATH' | cud -c 26-34
done
这两个脚本都有很大的改进空间,请随时贡献 -这是要点:)
您可以使用cmp
来比较文件大小,如下所示:
#!/bin/bash
folder1="$1"
folder2="$2"
log=~/log.txt
for i in "$folder1"/*; do
filename="${i%.*}"
cmp --silent "$folder1/$filename" "$folder2/$filename" && echo "$filename" >> "$log"
done
如果您出于任何原因不能使用 *dupes 并且文件数量非常sort+uniq
多,则不会有良好的性能。在这种情况下,您可以使用以下内容:
find . -not -empty -type f -printf "%012s" -exec md5sum {} \; | awk 'x[substr($0, 1, 44)]++'
find
将为每个文件创建一行,文件大小以字节为单位(我使用了 12 个位置,但 YMMV)和文件的 md5 哈希(加上名称)。
awk
将过滤结果而不需要预先排序。44 代表 12(文件大小)+ 32(哈希长度)。如果您需要有关 awk 程序的一些解释,您可以在此处查看基础知识。