【问题标题】:Compare md5 of all files in directory excluding multiple hardlinks比较目录中所有文件的 md5,不包括多个硬链接
【发布时间】:2020-07-20 19:06:03
【问题描述】:

我倾向于漫无边际,因此,如果为了削减谷壳而导致上下文较少(或者我只是悲惨地失败并且仍然漫无目的),我会提前道歉。

我正在尝试改进我编写的一些工具,用于将大量数据从一个网络存储位置同步到另一个以进行归档(第二个网络位置是更大磁带库系统的一部分)。由于大量共享资源,目录中通常有大量硬链接文件需要移动,我使用 rsync 来保留这些链接。

在 1TB 的实际数据区域中,当硬链接被“包含”到总数中时,Rsync 可能会大 4 或 5 倍(即 4 - 5TB)并不少见或意外。

出于各种原因,我需要对源中的数据进行哈希处理并与目标数据进行比较AND 记录该哈希结果(包括哈希)。因此,如果恢复的数据意外损坏,我可以比较恢复数据的哈希值和同一文件最初 rsync 时的哈希值,以确定何时/是否发生损坏。

rsync 发生后,我使用以下命令对源进行 md5(任何哈希都可以,但我没有具体原因选择 md5):

find . -type f -exec md5sum "{}" + > $temp_file

$temp_file 的输出也会回显到我的主输出文件中。然后移动到目的地并运行(这样做是先源然后目的地,好像文件夹正在合并,它只会散列在这个最新的rsync中移动的文件):

md5sum -c $temp_file >> $output_file

一切都很好,这确实有效除了,这将散列所有文件,包括硬链接,实际上,找到一遍又一遍地重复相同的文件,这可能会增加整个过程的时间。

有没有办法编辑 'find....' 命令以忽略硬链接文件,但是 仍然散列硬链接文件中的“原始”文件链接实际上指向。我确实研究了以下内容:

find . -type f -links 1

但我担心的是所有与硬链接相关的文件都将被忽略,而不是列出实际占用该 inode 的“原始”文件,并排除随后指向该 inode 的所有文件。

我对 -links 1 忽略所有硬链接相关文件是否正确,如果是,我该怎么办?

【问题讨论】:

  • 你可以编写一个备忘录脚本来构建一个 inode → 哈希缓存以避免重复计算。
  • 所有常规文件都是硬链接。如果一个 inode 有多个硬链接,则您无法判断哪个链接是首先创建的。您可以通过例如记住哈希值找到输出 inode 编号和文件名后,在 while read 循环中读取它们,并使用关联数组来跟踪您是否已经处理过这个 inode
  • 谢谢你们,这个信息很有帮助,也暴露了一些我真的不明白的地方(即所有常规文件都是硬链接),我很感激你们的信息!!

标签: bash rsync md5sum


【解决方案1】:

与软链接不同,硬链接是常规文件,每个文件都指向相同的 inode 编号,并且在概念上没有原始或重复的硬链接。

您可以在这里做的是使用-samefilefind 命令获取所有相同的硬链接,放入忽略列表,并使用此忽略列表跳过重复操作。

touch /tmp/duplicates
find . -type f | while read f
do
    if ! $(grep $f /tmp/duplicates &>/dev/null)
    then
        find . -samefile $f | grep -v $f >> /tmp/duplicates
        # put md5sum procedure for $f here
    fi
done

【讨论】:

  • 谢谢!!这显然是我对文件系统工作方式缺乏“深入”理解的情况。这是一个不错的解决方案(这也符合我使用临时文件进行各种编码的风格 - 并不是我不喜欢数组,只是它们的 bash 语法很笨拙且难以阅读!)。
【解决方案2】:

作为将每个文件与已处理文件列表进行比较的替代方法,请考虑使用 inode(如评论者所建议的那样)。根据树中文件的数量,它可能会通过删除他在树上重复的“查找”来节省时间。

#! /bin/bash

declare -A seen
find . -type f -printf '%i %p\n'  | while read inode file ; do
   [ "${seen[$inode]}" ] && continue
    seen[$inode]=$file
    # MD5 calculation ...
    md5sum $file
    ...
done

【讨论】:

  • 谢谢!我接受 anmol's 作为答案,因为他的 sn-p 符合我的编码风格,但我可以看到使用巨大的树如何更快,这确实发生了,所以我也会测试这个速度:) 谢谢你抽出宝贵的时间回应!
  • 抱歉重复评论。我只想添加以使其正常工作,我必须将find 修改为find . -type f -exec ls -i "{}" + 以使管道输出while read 循环的inode 和文件名。
  • @OwenMorgan 我已经修复了命令行。当我将我的解决方案复制到原始邮政编码中时,我错过了它。应该在没有 exec 的情况下工作,这将是一个很大的性能损失。
猜你喜欢
  • 2016-06-24
  • 2010-09-11
  • 1970-01-01
  • 2013-05-17
  • 1970-01-01
  • 2013-09-05
  • 2016-08-23
  • 2011-07-19
  • 1970-01-01
相关资源
最近更新 更多