从一个硬盘复制到另一个硬盘后验证大目录

从一个硬盘复制到另一个硬盘后验证大目录

我有一个使用 Ubuntu 的家庭文件服务器。

最近,我的一个驱动器已满,所以我又买了一个并把它扔在那里。

我有一个非常大的文件夹,目录大小约为1.7T,包含相当数量的文件。

我用了GCP将文件从旧驱动器复制到新驱动器,似乎工作正常。

我现在想根据旧驱动器上的原始目录验证新驱动器上的新目录,然后再从旧驱动器中删除数据以释放空间。我知道我可以通过 CRC 检查来做到这一点。

具体来说,我可以如何做到这一点?

答案1

我只需使用diff命令:

diff -rq --no-dereference /path/to/old/drive/ /path/to/new/drive/

这会读取并比较目录树中的每个文件并报告任何差异。该-r标志以递归方式比较目录,而该-q标志只是在文件不同时将消息打印到屏幕上,而不是打印实际差异(就像对文本文件那样)。--no-dereference如果存在不同的符号链接,例如,在一个目录中存在符号链接,而在其对应的目录中存在链接到的文件的副本,则该标志可能很有用。

如果diff命令打印无输出,这意味着目录树确实是相同的;可以运行echo $?验证其退出状态为0,说明两组文件是相同的。

我不认为计算 CRC 或校验和在这种情况下特别有用。如果两组文件位于不同的系统上,并且每个系统都可以计算自己的文件组的校验和,因此只需要通过网络发送校验和,则更有意义。计算校验和的另一个常见原因是保留校验和的副本以供将来使用。

答案2

同步通常用于复制文件而不是gcp,但它也可用于验证副本,无论副本是如何制作的。简单地做

rsync -niaHc /origfolder/ /copyfolder

请小心以/.选项有

  • -n请勿复制(请勿更改)
  • -i逐项列出差异
  • -a保留(即比较,因为我们有-n)权限、所有权、符号链接等并递归目录
  • -H保留硬链接
  • -c比较校验和

输出显示一个代码,详细说明每个不同文件或目录的差异。如果它们相同则没有输出。该代码具有一些列YXcstpoguax,其中每个字符是一个点(.如果比较的方面没问题),或者是一个字母:

Y is type of update: 
   < sent (not appropriate in this case)
   > need to copy 
   c missing file or directory
   h is hard link
   . no update
   * and rest of line is a message, eg *deleting
X file type: f file  d dir  L symlink  D device S special file
c checksum differs. + new item  " " same
s size differs
t timestamp differs
p permissions differ
o owner differ
g group differ
u (not used)
a acl differ
x extended attributes differ

例如,

.d..t...... a/b/                    directory timestamp differs
cL+++++++++ a/b/d -> /nosuch2       symbolic link missing
cS+++++++++ a/b/f                   special file missing (a/b/f is a fifo)
>f..t...... a/b/ff                  file timestamp differs
hf          a/b/xx1 => a/b/xx       files should be a hard linked
cLc.t...... a/b/z -> /tmp/hi2       symbolic link to different name
cd+++++++++ a/c/                    directory missing
>f+++++++++ a/c/i.10                missing file needs to be copied

请参阅man rsync下文--itemize-changes了解更多详细信息。如果第三列c或第四列存在差异s,则说明数据已严重损坏。其他标志(例如不同的权限、所有者或时间戳)对您来说可能不太重要。如果所有文件都被标记为“丢失”,那么您可能没有提供正确的目录进行比较。如果您确定,运行不带该-n标志的 rsync 将“修复”差异。

答案3

我有同样的问题,我用过安东尼的回答,有一点扭曲。

如果出现某些硬件故障(例如输入/输出错误),导致 diff 退出,直接应用他的答案将会失败。

我整理了他的答案,以及这个答案,并将其全部放入:

find /path/to/original -type f -exec bash -c 'diff -rq --no-dereference "$@" "/path/to/destination/$(sed -r "s/^.*(<first-common-ancestor>.*)$/\1/g" <<<"$@")"' bash {} \;
  • 替换/path/to/original为您复制的原始目录的路径。
  • 替换/path/to/destination为您复制到的目标目录的路径。
  • 替换<first-common-ancestor>为两者之间的共同祖先目录。示例:您正在从 复制/media/foo/bar/media/test/dst/,因此dst,在复制操作完成后, 具有目录bar。第一个共同祖先就bar在这里;因为下面的所有文件bar都将具有相同的相对路径。

一些注意事项:

  • bash -c和部分bash {}用于对文件名进行安全替换;为了安全起见,不要受到可能的攻击(例如特权提升)的伤害。
  • sed部分是删除找到的文件的绝对路径并仅使用相对路径(这与 using 不同execdir)。如果您不确定这有什么用,请尝试将其删除并检查错误消息:)
  • <<<变量作为字符串读取,而不是将其作为要读取的文件的路径读取。

相关内容