比较目录中所有文件的 md5,不包括多个硬链接

Compare md5 of all files in directory excluding multiple hardlinks

我倾向于东拉西扯,所以如果为了削减谷壳而导致上下文减少(或者我只是悲惨地失败并且仍然东拉西扯),我会提前道歉。

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

在 1TB 的实际数据区域进行 Rsyncing,当硬 link 进入总数时 'included' 可以大 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

一切都很好,这确实有效 EXCEPT,这将散列所有文件,包括 hard-links,实际上,一遍又一遍地查找相同文件的 md5 哈希值,这可能会增加整个过程的时间。

有没有办法编辑 'find....' 命令以忽略硬linked 文件,但是仍然散列 hard-link 实际指向的 'original' 文件。我确实调查了以下内容:

find . -type f -links 1

但我担心的是,所有与硬link相关的文件都将被忽略,而不是列出实际占用inode的'original'文件,并排除随后指向该inode的所有文件inode.

我关于 -links 1 忽略所有硬 link 相关文件是否正确,如果是这样,我能做什么?

与软链接不同,硬链接是常规文件,每个文件都指向相同的 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

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

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