1

В январе 2015 года я перенес некоторые файлы из образа резервной копии, созданной dd, на новый жесткий диск. Эта передача не сохранила метки времени, поэтому в основном каждый файл показывает метку времени 20 января.

С тех пор многие файлы были изменены, новые файлы были созданы и т.д., Но многие другие файлы по-прежнему идентичны (кроме метки времени) копиям на образе dd.

Я хотел бы рекурсивно копировать временные метки из файлов образа dd в соответствующие файлы на новом диске, но только если файлы идентичны (т.е. только если файлы не были изменены с момента оригинальной копии).

Я пробовал разные вещи с rsync, touch и т.д., Но я не смог понять это. Я думаю, что что-то вроде следующего psuedocode будет работать, но я очень незнаком с сценариями 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 ответ1

0

У меня была очень похожая потребность, поэтому вот мое решение.

Скрипты 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" ';'

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .