通过将重复文件与 MD5 进行比较来删除重复文件

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)

Att*_*tie 5

我会推荐类似以下的内容:

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