当文件结构发生变化时,比较两个目录中的文件(递归)

当文件结构发生变化时,比较两个目录中的文件(递归)

我意外删除了部分文件夹(在停止 rm 命令之前)。但是,我恢复的备份大约是 2 周前的,不幸的是,我在删除它们和备份时间点之间重命名并重组了目录。我手动恢复了我知道丢失的内容,但我不确定我是否设法恢复了所有内容。

有没有一种快速的方法来显示文件差异,不包括其父目录,只显示文件名和修改或创建日期?例如,我有目录

data/output/test1/file1.mha

我可能已经将其移动或重命名为

data/results/mhas/first_test/file1.mha

使用diff -rq这个方法不起作用,而且速度也相当慢。目录大小约为 2TB,文件数量相当多,因此检查每个文件的 MD5 几乎是不可能的。


稍微澄清一下,恢复备份后,我:

/data_backup_restore/output/test1/file1.mha

/data/results/mhas/first_test/file1.mha

因为恢复的备份仍然使用“旧”目录结构。我已经更改了它,因为它很乱,但我没有写下我所做的所有更改/重命名,因为它们太多了。
如果文件大小、修改日期和文件名匹配,我会将上述两者视为相同。

答案1

如果我理解正确的话,您想递归地比较两个目录,但忽略目录结构,所以基本上如果您在两棵树中找到两个具有相同文件名、创建/修改时间和大小的文件(您没有提到大小,但我想它也会很有用),那么将它们视为相同的,即使它们在两个目录树中位于不同的位置。

如果正确的话,您可以创建一个包含大小、时间和文件名的文件列表,如下所示:

ls -lR --time-style=long-iso /data/output/  | grep ^- | tr -s ' ' | cut -d' ' -f5- | sort -k 4 >files_output.txt
ls -lR --time-style=long-iso /data/results/  | grep ^- | tr -s ' ' | cut -d' ' -f5- | sort -k 4 >files_results.txt

然后使用diff或者类似的 GUI比较这两个列表meld

细节:

  • 使用--time-style=long-iso以避免可能破坏以下管道的区域特定特性。
  • grep ^-仅选择实际文件,忽略目录和可能的其他特殊文件。根据您的使用情况,您可能希望在此处添加更多内容,例如符号链接...
  • tr -s ' '将挤压多个连续的空格以使以下内容cut在所有情况下都能正常工作。
  • cut从第 5 列开始的列(文件大小)
  • sort以便稍后进行比较。-k 4实际上没有必要,只要两个命令一致即可。-k 4将按文件名排序,这可能会有用。

在您比较两个文件并发现差异之后,您当然必须在原始目录树中找到该文件,您可以使用find它。

更新

根据您的评论,如果您想查找多次出现的文件名的完整路径,您可以执行以下操作:

首先获取第二个目录中缺少的文件列表,例如:

comm -1 -3 file_outputs.txt file_results.txt >missing_files.txt

然后,对于每个丢失的文件,使用 find 查找特定文件的完整路径:

cat missing_files.txt | while read size date time name
do
    find . -name "$name" -size ${size}c -newermt "$date $time" ! -newermt "$date $time +0000 +1 minutes"
done

现在请注意,这只是一个简单的示例,并非最佳选择,并且根据丢失文件的数量,它会find多次调用该示例,如果目录很大(如您所指出的那样),则可能会很慢。在这种情况下,您应该尝试以某种方式对其进行优化(例如,列出所有与文件相似但ls -lR包含完整路径的文件,并尝试将该列表与您在文件中找到的列表进行匹配missing.txt)。

答案2

要比较文件内容,您可以使用以下命令:

find FolderA -type f -print0 | xargs -0 cksum > FoldA.cksum
find FolderB -type f -print0 | xargs -0 cksum > FoldB.cksum

您可以将这两个文件一起排序。由于前两个字段是校验和和大小,因此您可以忽略具有相同校验和和大小的两个组。一组表示一个文件夹中缺少一个文件。

来源 : 递归比较大目录 - 但忽略子目录 - 比较两个备份 - 使用 gui

答案3

一种可能的方法是使用哈希:

cd /directory1
sha1sum * **/* >/tmp/sum
cd /directory2
sha1sum -c /tmp/sum

奇怪的构造**/*是在子目录中搜索(globbing应该启用),这将在第一个目录中生成文件的哈希值,并使用第二个目录中的哈希值进行检查,并指示 OK 文件和缺失/不匹配的哈希值:

#a/aa: OK
rr: OK
zzz: FAILED
sha1sum: WARNING: 1 of 3 computed checksums did NOT match

PS 不要害怕使用哈希函数,它们非常快

相关内容