查找具有相同文件名和完全相同大小的重复文件

Ele*_*ngs 6 fedora find mp3 search deduplication

我有一个巨大的歌曲文件夹,结构混乱,文件重复在多个文件夹中。

我需要推荐一个工具或脚本,可以通过简单的两个匹配来查找和删除重复项:

  1. 完全相同的文件名
  2. 文件大小完全相同

在这种情况下,和song.mp3中存储的文件大小为 1234 字节。工具/脚本应仅保留一份副本。/songs/album1/songs/albumz

我在 Fedora 上尝试过czkawka,但它可以按文件名或文件大小进行搜索,但不能将两者组合在一起进行搜索。

Sea*_*mus 6

rdfind可能会执行您想要的操作,但您需要依赖加密哈希/校验和(md5、sha1 或 sha256)来代替文件大小。

哈希值是比文件大小更严格的标准,但这可能是也可能不是您想要的。例如,考虑音乐文件中的所有元数据Schubert:如果一个被列为作曲家的文件,而另一个被列为Bruckner作曲家的潜在重复文件以及文件中的其他所有内容都完全相同,则文件大小过滤器会将其分类为匹配,但哈希过滤器不会。哈希过滤器将使用比文件大小过滤器更多的资源,但如果您只是偶尔过滤重复项,这可能不是问题。

在实际运行之前rdfind,请务必man rdfind仔细阅读并使用该-dryrun选项,直到您确信结果是您想要的为止。

FWIW,本教程列出了rdfind和其他 3 个用于查找重复文件的实用程序。

我不知道有一种可以过滤文件大小的工具,但如果我从头开始创建一个工具,我想我会使用find和拼凑一些东西awk。让我们知道这是否是您想要的 - 我认为这并不是非常困难,但如果满足您的需求也没有多大意义rdfind


db-*_*inf 2

您确实不需要为此使用外部实用程序。通过链接一组标准命令,您可以走很远的路,通过将它们存储在 shell 脚本或函数中,您可以始终记住它们。

要检测重复项,您可以将所有文件路径存储在关联数组中,以大小加文件名为键。但因为您表明您有一个很大的文件集合,所以我建议改为进行排序。然后使用唯一选项进行第二次排序,以便比较两个结果可以得出重复项。

  1. 您想使用第一次排序的输出两次。我可以为此使用临时文件;对于这个简单的工作,命名管道和 fifo 等并不需要更少的工作。该命令将为您mktemp打印目录中安全唯一的文件名。/tmp/使用命令替换结构$(...),您可以将该名称分配给名为的变量tmp或其他名称。回显它就知道你在做什么。

  2. 现在您想要使用 2 个关键字段:大小和文件名,并且还需要完整路径。方便的是斜杠/不是有效的文件名字符:它保留用于分隔目录名和文件名。因此,您可以使用/作为这 3 个字段之间的分隔符。-printf该命令的操作可以find为您提供:找到所有-type f(ile),并打印它们的大小%s、文件名%f和完整路径%p,所有内容均以 分隔/。完整路径将包含更多斜杠,但我们知道只有前 2 个斜杠分隔符(我们在格式中明确指定的斜杠分隔符)-printf是我们的。

  3. 将命令|的输出find(大小、文件名和完整路径的列表)通过管道传输到sort命令。告诉它字段由斜杠分隔:-t /,并且密钥位于前 2 个字段中:-k 1,2。您可以立即将排序后的列表存储在临时文件中,但我选择让tee命令执行此操作,因为这样您可以保持一个管道打开,以获得更好的性能。

  4. |将排序后的列表通过管道传输到tee,它将其副本存储到给定的 filename "$tmp",并在某种程度上将管道回显到下一个管道。

  5. Pipe| tee将排序后的列表回显到第二个,在相同的键上,但现在在排序键中sort输出-uor 。--unique

  6. |唯一大小+文件名条目的列表通过管道传递给diff命令作为第一个输入-stdin),并使用临时文件"$tmp"作为第二个输入。通常diff会在其输出中添加一些标记,以便您可以识别更改的性质。但我们不需要它,而且它会扰乱我们需要的输出。我们知道唯一列表的每个条目也在完整列表中。我们只想要完整列表中的普通额外行。这就是命令的选项所diff要求的。

  7. 到目前为止的命令将输出一个希望简短的具有重复文件的列表。每组重复项中的一个被省略,因为它仍然出现在唯一列表中。为了处理该列表的每个条目,并对其最后一部分(完整路径名)进行操作,我们将|其通过管道传输到一个while read构造中。它将每一行存储在给定的参数名称下dupl。使用 bash 参数扩展语法,#我们省略了前缀*/*/,即大小加上文件名及其斜杠/分隔符,剩下的是文件副本的完整路径。我建议您首先执行完整的命令echo,并在仔细检查后将其替换为删除rm命令,或者更好的是,使用其中一个垃圾桶实用程序将重复项移动到 yuor Trash,以便清理您的目录,但什么也没有丢失了。

    tmp=$(mktemp)
    echo temp file is "$tmp"
    find -type f -printf "%s/%f/%p\n" |
     sort -t / -k 1,2 |
     tee "$tmp" |
     sort -t / -k 1,2 -u |
     diff --new-line-format="%L" --unchanged-line-format="" - "$tmp" |
     while read dupl;do echo "${dupl#*/*/}"; done
    rm "$tmp"
    
    Run Code Online (Sandbox Code Playgroud)
  8. 后面收拾一下,把临时文件清理干净"$tmp"