跨目录树同步相同文件的时间戳?

跨目录树同步相同文件的时间戳?

2015 年 1 月,我将一些文件从 dd 创建的备份映像传输到新硬盘。此传输未保留时间戳,因此基本上每个文件都显示 1 月 20 日的时间戳。

从那时起,许多文件已经被修改,新的文件已经被创建等等,但是更多的文件仍然与 dd 图像上的副本相同(时间戳除外)。

我想以递归方式将 dd 映像文件中的时间戳复制到新磁盘上的匹配文件中,但前提是文件相同(即,前提是文件自原始副本以来没有被修改过)。

我尝试过 rsync、touch 等各种方法,但还是没能搞定。我认为类似下面的伪代码可以工作,但我对 bash 脚本非常不熟悉。

for each file_in_dd_image
if (md5sum(file_in_dd_image) == md5sum(file_on_harddisk))
touch file_on_harddisk --reference=file_in_dd_image

或者,也许更好,因为如果文件在传输后被移动它也会起作用,有没有什么方法可以处理输出jdupes -rO dd_image harddisk

任何帮助将不胜感激!

答案1

我有非常类似的需求,所以这是我的解决方案。

Bash 脚本可能有点棘手,特别是涉及带有空格的文件名时,如果您做错了,最终可能会造成严重破坏,因此最好将其分成可管理、可测试的部分。

第 1 部分,仅对一个文件执行所需行为的脚本:

#!/bin/bash

# Usage: copy_timestamp_if_identical.sh source_file dest_file

test "$#" -eq 2 || { echo "Wrong number of arguments" >&2; exit 1; }

FILE1="$1"
FILE2="$2"

test -f "$FILE1" || { echo "File \"$FILE1\" not found"  >&2; exit 1; }
test -f "$FILE2" || { echo "File \"$FILE2\" not found"  >&2; exit 1; }

if test "$(basename "$FILE1")" != "$(basename "$FILE2")";
then
    # Not same filename
    exit;
fi

if test $(md5sum "$FILE1" | cut -d ' ' -f 1) != $(md5sum "$FILE2" | cut -d ' ' -f 1);
then
    # Not same contents
    exit;
fi

echo "Updating \"$FILE2\" from \"$FILE1\""
touch -r "$FILE1" "$FILE2"

第2部分:

使用“find”来递归查找文件,这可能是比较棘手的部分。

这还允许更高级的条件,包括指定修改日期,这样您就可以避免触摸绝对不应该触摸的东西,以确保安全和速度。请-mtime参阅man find

例如,要查找最后修改时间戳为 1 年前或更早的所有文件:

find "DEST_DIRECTORY" -type f -mtime +365

其中 DEST_DIRECTORY 是您要修复的目录。选中此项将返回您要修复的文件。

第 3 部分:

将以上两部分结合起来。这有点棘手,因为需要将两个不同的文件传递给,这对于和copy_timestamp_if_identical.sh来说并不容易。最后我决定编写一个辅助脚本:find-exec

#!/bin/bash

# Usage: copy_timestamp_if_identical_helper.sh file_in_dest_dir source_dir dest_dir

test "$#" -eq 3 || { echo "Wrong number of arguments" >&2; exit 1; }

DEST_FILE="$1"
SRC_DIR="$2"
DEST_DIR="$3"

SRC_FILE="$SRC_DIR${DEST_FILE:${#DEST_DIR}}"

echo copy_timestamp_if_identical.sh "$SRC_FILE" "$DEST_FILE"

您必须将源目录和目标目录以及要修改的文件传递给它,因此组合解决方案如下所示:

find "DEST_DIR" -type f -mtime +365 -exec copy_timestamp_if_identical_helper.sh '{}' "SOURCE_DIR" "DEST_DIR" ';'

相关内容