Иногда мне приходится копировать / синхронизировать большие объемы данных в структуре каталогов с одного компьютера на другой. Типичными программами, которые я использую для этой цели, являются rsync, syncthing или seafile.

Чтобы не полагаться исключительно на правильность программы копирования / синхронизации (или выбранных мной опций), я обычно генерирую файл контрольной суммы (используя cfv) в родительском каталоге и копирую / синхронизирую его с данными, чтобы потом можно было проверить на конечном компьютере все в порядке. Например, cfv хорошо работает, чтобы увидеть, все ли файлы из источника благополучно прибыли.

Однако я пропускаю один из вариантов, чтобы посмотреть, есть ли в копии файлы, которых не было в оригинале. Насколько я могу судить, у cfv нет возможности искать такие "дополнительные" файлы. Решение, к которому я прибегаю, состоит в том, чтобы создать новый файл контрольной суммы для копии и сравнить его с оригиналом, но это означает, что контрольные суммы для каждого файла должны быть вычислены четыре раза (создание и проверка на обоих компьютерах).

Есть ли лучшее решение?

2 ответа2

2

Вычисление контрольных сумм выглядит для меня излишним, если вы хотите обнаружить только "дополнительные" файлы. Вам не нужно проверять фактические данные (содержимое файла); вам нужно проверить метаданные (существующие пути).

Чтобы получить все относительные пути внутри /synced/dir , запустите

(cd /synced/dir && find . | sort) > structure.txt

Сделайте это с обеих сторон, затем diff полученные файлы. Обратите внимание, что ситуация симметрична, поэтому вы обнаружите "дополнительные", а также "отсутствующие" файлы на любой стороне ("дополнительные" здесь эквивалентны "отсутствующим" там, и наоборот).

Чтобы игнорировать "дополнительные" файлы на одной (или другой) стороне, отфильтруйте вывод diff с помощью grep '^>' (или grep '^<' соответственно).

Если две директории доступны (смонтированы) в одной системе, этот синтаксис Bash может быть полезен:

diff <(cd /original/dir && find . | sort) <(cd /backup/dir && find . | sort) | grep '^>'

Это не совсем надежно (например, переводы строк в именах файлов могут нарушить логику), мой пример более похож на доказательство концепции. Дело в том, что вы обнаруживаете дополнительные файлы, не читая содержимое файла вообще.

Заметки:

  • sort необходима, потому что два find -s могут возвращать записи в различной последовательности, даже если каталоги являются точными копиями;
  • sole diff может сравнивать каталоги, но этот режим здесь бесполезен, потому что он пытается сравнивать содержимое соответствующих файлов, такого поведения мы хотим избежать в первую очередь.
0

Ответ Камиля Мачоровского очень хороший, но я думаю, что его решение можно упростить в контексте, изложенном в вопросе, с помощью следующей процедуры:

1) Создайте файл контрольной суммы на источнике. Вот скрипт bash, который делает это с помощью cfv:

#!/bin/bash

# create md5 checksum file for all files in the current directory tree

# filename for checksum file
FN="${PWD##*/}.md5"

# create checksum file
cfv -rr -C -L -t md5 -f $FN

Он начинается с текущего каталога, рекурсивно спускается, не следуя символическим ссылкам, и создает единственный файл контрольной суммы в текущем каталоге.

2) Синхронизация / копирование из источника в место назначения.

3) Проверьте файл контрольной суммы в месте назначения (используя cfv) и найдите дополнительные файлы, используя find , sort и comm:

#!/bin/bash

# test md5 checksum file w.r.t. all files in the current directory tree

# filename for checksum file
FN="${PWD##*/}.md5"

# test checksum file
cfv -T -f $FN

# check whether there are additional files
echo ----------- additional files -----------
CHECK=`tempfile`
sed  's .\{34\}  ' $FN | sort > $CHECK
LOCAL=`tempfile`
find -P -type f -printf '%P\n' | sort > $LOCAL
comm -13 $CHECK $LOCAL

Отличие от ответа Камиля Макиоровского состоит в том, что я не создаю отдельный список файлов для источника, но использую имена файлов в файле контрольной суммы, извлеченном с помощью sed . Предполагается, что файл контрольной суммы имеет стандартный формат md5sum : 32-символьная контрольная сумма, пробел, '*' или '' для обозначения двоичного / текстового режима, имя файла.

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