Папки слияния 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.