&2; exit-6ren">
gpt4 book ai didi

bash - 如何找到重复的目录

转载 作者:行者123 更新时间:2023-11-29 08:55:11 25 4
gpt4 key购买 nike

让我们创建一些测试目录树:

#!/bin/bash

top="./testdir"
[[ -e "$top" ]] && { echo "$top already exists!" >&2; exit 1; }

mkfile() { printf "%s\n" $(basename "$1") > "$1"; }

mkdir -p "$top"/d1/d1{1,2}
mkdir -p "$top"/d2/d1some/d12copy
mkfile "$top/d1/d12/a"
mkfile "$top/d1/d12/b"
mkfile "$top/d2/d1some/d12copy/a"
mkfile "$top/d2/d1some/d12copy/b"
mkfile "$top/d2/x"
mkfile "$top/z"

结构为: find testdir \( -type d -printf "%p/\n" , -type f -print \)
testdir/
testdir/d1/
testdir/d1/d11/
testdir/d1/d12/
testdir/d1/d12/a
testdir/d1/d12/b
testdir/d2/
testdir/d2/d1some/
testdir/d2/d1some/d12copy/
testdir/d2/d1some/d12copy/a
testdir/d2/d1some/d12copy/b
testdir/d2/x
testdir/z

我需要找到重复的 目录 ,但我只需要考虑文件(例如,我应该忽略没有文件的(子)目录)。因此,从上面的测试树中,想要的结果是:
duplicate directories:
testdir/d1
testdir/d2/d1some

因为在两个(子)树中只有两个相同的文件 ab . (和几个目录,没有文件)。

当然,我可以 md5deep -Zr . ,也可以使用 perl 走整棵树脚本(使用 File::Find + Digest::MD5 或使用 Path::Tiny 或类似。)并计算文件的 md5-digests,但这无助于找到重复的 目录 ... :(

知道如何做到这一点吗?老实说,我没有任何想法。

编辑
  • 我不需要工作 code . (我可以自己编写代码)
  • 我“只是”需要一些想法“如何处理”问题的解决方案。 :)

  • 编辑 2

    背后的基本原理 - 为什么需要这个:由于错误的备份策略,我从许多外部 HDD 复制了大约 2.5 TB 的数据。例如。多年来,整个 $HOME目录被复制到(许多不同的)外部硬盘驱动器中。许多子目录具有相同的内容,但它们位于不同的路径中。所以,现在我试图消除相同内容的目录。

    我需要这样做 按目录 ,因为这里是目录,其中有一些重复文件,但不是全部。让说:
    /some/path/project1/a
    /some/path/project1/b


    /some/path/project2/a
    /some/path/project2/x

    例如 a是一个重复的文件(不仅是名称,还有内容)-但这两个项目都需要它。所以我想保留 a在两个目录中 - 即使它们是重复的文件。因此,我在寻找如何找到重复目录的“逻辑”。

    最佳答案

    一些关键点:

  • 如果我理解正确(从你的评论中,你说:“(另外,当我说相同的文件时,我的意思是它们的内容相同,而不是它们的名称)”,你想要找到重复的目录,例如它们的内容完全相同就像在其他目录中一样, 与文件名无关 .
  • 为此,您必须为文件计算一些校验和或摘要。相同的摘要 = 相同的文件。 (很有可能)。 :) 正如你已经说过的,md5deep -Zr -of /top/dir是一个很好的起点。
  • 我添加了 -of ,因为对于此类工作,您不需要计算符号链接(symbolic link)目标或其他特殊文件(如 fifo)的内容 - 只是普通文件。
  • 计算 md5对于 2.5TB 树中的每个文件,肯定需要几个小时的工作,除非你有非常快的机器。 md5deep为每个 CPU 核心运行一个线程。因此,当它运行时,您可以制作一些脚本。
  • 另外,请考虑运行 md5deepsudo ,因为如果长时间运行后您会收到一些关于无法读取的文件的错误消息,这可能会令人沮丧,这仅仅是因为您忘记更改文件所有权...(请注意):) :)

  • 对于“如何”:
  • 为了比较“目录”,您需要计算一些“目录摘要”,以便于比较和查找重复项。
  • 最重要的一件事是意识到以下关键点:
  • 您可以排除目录,其中包含具有唯一摘要的文件。如果文件是唯一的,例如没有任何重复项,这意味着检查它的目录毫无意义。某个目录中的唯一文件意味着该目录也是唯一的。因此,脚本应该忽略每个目录,其中包含唯一 MD5 的文件。摘要(来自 md5deep 的输出。)
  • 您不需要从文件本身计算“目录摘要”。 (正如您在 your followup question 中尝试的那样)。使用已经计算的文件的 md5 计算“目录摘要”就足够了,只需确保您先对它们进行排序!

  • 例如例如,如果您的目录 /path/to/some仅包含两个文件 ab
    if file "a" has md5 : 0cc175b9c0f1b6a831c399e269772661
    and file "b" has md5: 92eb5ffee6ae2fec3ad71c777531578f

    您可以从上述文件摘要中计算“目录摘要”,例如使用 Digest::MD5你可以这样做:
    perl -MDigest::MD5=md5_hex -E 'say md5_hex(sort qw( 92eb5ffee6ae2fec3ad71c777531578f 0cc175b9c0f1b6a831c399e269772661))'

    并会得到 3bc22fb7aaebe9c8c5d7de312b876bb8作为您的“目录摘要”。排序在这里很重要(!),因为相同的命令,但没有排序:
    perl -MDigest::MD5=md5_hex -E 'say md5_hex(qw( 92eb5ffee6ae2fec3ad71c777531578f 0cc175b9c0f1b6a831c399e269772661))'

    生产: 3a13f2408f269db87ef0110a90e168ae .

    请注意,即使上述摘要不是您文件的摘要,但它们对于包含不同文件的每个目录都是唯一的,并且对于相同的文件也是相同的。 (因为相同的文件,具有相同的 md5 文件摘要)。排序可确保您始终以相同的顺序计算摘要,例如如果其他目录将包含两个文件
    file "aaa" has md5 : 92eb5ffee6ae2fec3ad71c777531578f
    file "bbb" has md5 : 0cc175b9c0f1b6a831c399e269772661

    使用上述 sort and md5你会再次得到: 3bc22fb7aaebe9c8c5d7de312b876bb8 - 例如包含与上述相同文件的目录...

    因此,通过这种方式,您可以为您拥有的每个目录计算一些“目录摘要”,并且可以确保如果您获得另一个目录摘要 3bc22fb7aaebe9c8c5d7de312b876bb8这就是说:这个目录正好有以上两个文件 ab (即使他们的名字不同)。

    这种方法很快,因为您将仅从 32 字节的小字符串计算“目录摘要”,因此您避免了过多的多个文件摘要计算。

    现在最后一部分很容易了。您的最终数据应采用以下形式:
    3a13f2408f269db87ef0110a90e168ae /some/directory
    16ea2389b5e62bc66b873e27072b0d20 /another/directory
    3a13f2408f269db87ef0110a90e168ae /path/to/other/directory

    所以,从这里很容易得到:
    /some/directory/path/to/other/directory是相同的,因为它们具有相同的“目录摘要”。

    嗯... 以上所有只是几行长的 perl 脚本。在这里直接将 perl 脚本写成上面的长文本答案可能会更快-但是,您说-您不需要代码... :) :)

    关于bash - 如何找到重复的目录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43560796/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com