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


13

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

src/
dest/

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

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

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

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

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

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

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

Ответы:


17

Я провел только ограниченное тестирование функциональности, поэтому будьте осторожны с этой командой (--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"' {} \;

если имена файлов могут содержать пробелы / новые строки /… Что касается комментария Жиля о специальных символах, то это, безусловно, что-то, о чем следует помнить, и есть много решений, самым простым будет передать -i в rm, который будет запрашивать перед всем удалением. Однако при условии, что для поиска указан src / или его родительский путь, полный путь должен привести к тому, что все имена файлов будут правильно обрабатываться командами diff и rm без кавычек.


исправление: эта команда не удалит файлы из src, если идентичная копия уже существует в dest
Tok

Да :(. Эту часть мне трудно понять.
Дэвид Онеилл

2
Что ж, хорошая новость заключается в том, что вы можете решить ее самостоятельно без особых хлопот: for file in `find src/ -type f`; do diff $file `echo $file | sed 's/src/dest/'` && rm $file || echo $file; done(вы можете пропустить, || echo $fileесли хотите, оно включено для полноты)
Tok

Отличный: это то, что мне было нужно. Отредактируйте это в своем ответе, и я приму это!
Дэвид Онеилл

@Tok: Ваша команда будет подавлять имена файлов, которые содержат специальные символы (пробел,, \?*[начальный -). Вам нужно использовать двойные кавычки вокруг подстановок переменных , передавать --утилиты перед именами файлов, использовать find … -exec …вместо анализа выходных данных find. С rmкомандой в миксе, это - рецепт для катастрофы.
Жиль "ТАК ... перестать быть злым"

6

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


Он не выполняет в точности то, о чем просит ОП, но похоже, что он достигает конечной цели ОП. +1
Райан К. Томпсон

+1 К сожалению, на сервере, на котором я работаю, не установлен унисон, и у меня нет прав для его установки. Но это может быть хорошим ответом кому-то еще.
Дэвид Онеил

1
Вы можете скачать исполняемый файл unison с seas.upenn.edu/~bcpierce/unison//download/… . Установите его где-нибудь в вашем домашнем каталоге, это всего лишь один файл.
JooMing

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 .

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.