Папки слияния Linux: rsync?

У меня есть две копии папки

src/
dest/

Я хочу объединить их, делая следующее:

Если файл только в srcЯ хочу, чтобы это было перенесено в dest

Если файл только в destЯ хочу, чтобы он игнорировал IE, оставленный в покое.

Если файл находится в обоих файлах и имеет одинаковое содержимое (IE одинакового размера и даты), удалите из src

Если файл находится в обоих и не имеет идентичного содержимого, оставьте в src так что я могу вручную слить их.

Только очень небольшое количество файлов (от 0% до 5% от общего количества файлов) должно быть в этой последней категории, но я не знаю, как отделить в обоих и одинаковые от обоих, но разные.

Я пытался выяснить, как это сделать с rsync но пока безрезультатно.

3 ответа

Решение

Я провел только ограниченное тестирование функциональности, поэтому будьте осторожны с этой командой (--dry-run):

rsync -avPr --ignore-existing --remove-source-files src/ dest

Пожалуйста, обратите внимание на конечный символ /, поскольку он будет возвращаться в src вместо того, чтобы копировать сам src, это должно поддерживать ваши существующие пути.

Используя флаг --ignore-существующие в сочетании с флагом --remove-source-files, вы будете удалять только файлы из src, которые синхронизированы из src в dest, то есть файлы, которые ранее не существовали только в dest.

Для удаления несинхронизированных файлов, которые уже существуют в dest/ as в src/, вы можете использовать:

for file in `find src/ -type f`; do diff $file `echo $file | sed 's/src/dest/'` && rm $file || echo $file; done

или же

find src -type f -exec bash -c 'cmp -s "$0" "${0/#src/dest}" && rm "$0"' {} \;

if filenames could contain whitespace/new lines/… Regarding Gilles' comment concerning special characters, that is certainly something to be mindful of and there are many solutions, the simplest would be to pass an -i to rm which will prompt before all deletion. Provided that src/, or its parent path, is provided to find, however, the fully qualified path should result in all file names being handled properly by both the diff and rm commands without quoting.

Унисон - это инструмент, который вы ищете. Попробуйте unison-gtk, если вы предпочитаете графический интерфейс. Но я не думаю, что он удалит похожие файлы: в унисон постарайтесь, чтобы оба каталога были одинаковыми. Тем не менее, это легко: 1) определить, какие файлы копировать; 2) какие из них требуют ручного слияния.

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

cd src
find . -exec sh -c '
    set -- "/path/to/dest/$0"
    if [ -d "$0" ]; then #  the source is a directory 
      if ! [ -e "$1" ]; then
        mv -- "$0" "$1"  # move whole directory in one go
      fi
    elif ! [ -e "$0" ]; then  # the source doesn't exist after all
      :  # might happen if a whole directory was moved
    elif ! [ -e "$1" ]; then  # the destination doesn't exist
      mv -- "$0" "$1"
    elif [ -f "$1" ] && cmp -s -- "$0" "$1"; then  # identical files
      rm -- "$0"
    fi
  ' {} \;

Другой подход заключается в монтировании объединения один каталог над другим, например, с помощью funionfs или unionfs-fuse.

Другие вопросы по тегам