man*_*ndy 2 script bash bash-scripting
我想根据它们的 MD5 值删除重复的文件。我已经在下面找到了脚本,但是如何修改它以使其递归运行?
因此,例如我有包含 3 个子文件夹 A B C 的文件夹
我希望 ./ ./A/ ./B/ ./C/ 中的所有文件检查它们的 md5 并相互比较,如果发现正匹配,则随机删除任一匹配。最终不再存在重复项。我不在乎哪个匹配首先被删除。
我希望我清楚地表达了我需要实现的目标,如果没有,请告诉我:)
#!/bin/bash
while true
do
echo "Enter the directory:"
read directory
if [ -d $directory ]; then
break
else
echo "Invalid directory"
fi
done
for FILE in `ls $directory`
do
if [ ! -f $FILE ]; then
break;
fi
h=`md5sum $directory/$FILE | awk '{ print $1 }'`
for f in `ls $directory`
do
if [ -f $f ] && [ $FILE != $f ]; then
s=`md5sum $directory/$f | awk '{ print $1 }'`
if [ "$s" = "$h" ]; then
echo Removing $f
rm -rf $directory/$f
fi
fi
done
done
Run Code Online (Sandbox Code Playgroud)
我会推荐类似以下的内容:
find . -type f \
| xargs md5sum \
| sort -k1,1 \
| uniq -Dw32
Run Code Online (Sandbox Code Playgroud)
这将列出具有相同 MD5 哈希值的文件组中的所有重复文件。
注意,因为-w32参数 touniq只会比较前 32 个字符......如果你改变散列的长度,你需要更新它。
考虑以下树,其内容如下:
find . -type f \
| xargs md5sum \
| sort -k1,1 \
| uniq -Dw32
Run Code Online (Sandbox Code Playgroud)
./a/1: foo
./a/2: bar
./b/3: hello world
./b/d/5: bar
./c/4: foo
Run Code Online (Sandbox Code Playgroud)
您现在可以逐行处理这些行……每一行的前面都有一个匹配的哈希值,指向一个可以重复数据删除的文件。
如果您不太担心删除哪个文件,那么可以使用以下方法:
find . -type f \
| xargs md5sum \
| sort -k1,1 \
| uniq -Dw32 \
| while read hash file; do
[ "${prev_hash}" == "${hash}" ] && rm -v "${file}"
prev_hash="${hash}";
done
Run Code Online (Sandbox Code Playgroud)
请注意,MD5 不再被认为是安全的......所以如果您在用户可以控制文件的系统中使用它,那么他们可以设计冲突 - 因此您会意外删除合法/目标文件而不是像您希望的那样进行重复数据删除。更喜欢更强的哈希,比如SHA-256。