【问题标题】:Finding duplicate files according to md5 with bash用bash根据md5查找重复文件
【发布时间】:2013-11-02 07:58:59
【问题描述】:

我想写一个关于 bash 的算法,它可以找到重复的文件

如何添加尺寸选项?

【问题讨论】:

    标签: bash shell


    【解决方案1】:
    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 . 更改为适合您要搜索的目录。

    【讨论】:

    • 经常默认安装sha1,为什么还要使用md5?自从这个发现大约十年后,md5 就出现了碰撞问题
    • 不错,@GillesQuenot,但 md5 和 sha1 都坏了。这些天我建议使用 sha256/sha512,但在权衡性能和安全收益时要务实。 md5sum/sha1 对于某些用例仍然可以。
    • 我们如何修改它以删除除第一个之外的所有重复项?最好保留输出以告知我们正在发生的事情。
    【解决方案2】:

    find /path/to/folder1 /path/to/folder2 -type f -printf "%f %s\n" | sort | uniq -d

    find 命令在两个文件夹中查找文件,仅打印文件名(去除前导目录)和大小,仅排序和显示重复文件。这确实假设文件名中没有换行符。

    【讨论】:

      【解决方案3】:

      您可以使用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
      

      【讨论】:

        【解决方案4】:

        不要重新发明轮子,使用正确的命令:

        fdupes -r dir
        

        参见http://code.google.com/p/fdupes/(在某些 Linux 发行版上打包)

        【讨论】:

        • fdupes 有相当严重的性能问题。我试图找到大约 200 个非常大的视频文件的骗子。 fdupes 花了大约一个小时来扫描它。我的脚本执行了一些简单的技巧,花了大约 4 分钟。
        • 在 Mac 上您可以“brew install fdupes”。我喜欢这个,因为你可以传递一个额外的命令来自动删除第二个引用。性能方面,我在一个包含 50,000 个视频和图像(一些视频 1GB 或更大)的文件夹中运行它,并在 2 分钟左右完成。请务必在删除之前先进行测试运行。
        【解决方案5】:

        通常我使用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 sn -p:

        ## 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
        

        这两个脚本都有很大的改进空间,请随时贡献 - here is the gist :)

        【讨论】:

          【解决方案6】:

          这可能是一个较晚的答案,但现在有比fdupes 更快的替代方案。

          1. fslint/findup
          2. jdupes,它应该是 fdupes 的更快替代品

          我有时间做了一个小测试。对于在标准 (8 vCPU/30G) Google 虚拟机上包含 54,000 个文件、总大小为 17G 的文件夹:

          • fdupes 耗时 2m 47.082s
          • findup 需要 13.556 秒
          • jdupes 耗时 0.165 秒

          但是,我的经验是,如果您的文件夹太大,时间也可能会变得很长(数小时,如果不是数天),因为成对比较(或最好是排序)和极度消耗内存的操作很快就会变得难以忍受.在整个磁盘上运行这样的任务是不可能的。

          【讨论】:

            【解决方案7】:

            如果您出于任何原因无法使用 *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 程序的一些解释,您可以查看基础知识here

            【讨论】:

              猜你喜欢
              • 2010-12-06
              • 1970-01-01
              • 2020-09-09
              • 1970-01-01
              • 2015-05-09
              • 2017-07-24
              • 2021-04-18
              • 2014-02-16
              • 1970-01-01
              相关资源
              最近更新 更多