Вариант 1: вернитесь во времени и прочитайте это: http://lincolnloop.com/blog/2012/jan/6/detecting-file-moves-renames-rsync/ Это использует трюк с жесткими ссылками для оптимизации операции (обратите внимание, внимательно упущение завершающего символа "/" в этом примере может отличаться от того, к чему вы привыкли). Если у вас есть локальная резервная копия до реорганизации, вы, возможно, сможете восстановить и использовать ее (сложность заключается в том, что вы можете создать копию в виде жесткой ссылки по мере необходимости).
Вариант 2: если у вас нет пробелов / кавычек в именах файлов или каталогов, и вы не собираетесь хранить дубликаты, вы можете создать скрипт быстрого и грязного копирования / переименования, подобный этому.
По источнику:
cd /wherever
find . -type f | xargs sha1sum | sort > /tmp/src.out
По назначению
cd /wherever
find . -type f | xargs sha1sum | sort > /tmp/dst.out
Скопируйте файл dst.out
в источник, а затем в источнике выполните:
join -j 1 /tmp/src.out /tmp/dst.out | while read sum src dst; do
if [ "$src" != "$dst" ]; then
echo mkdir -p $(dirname "$src")
echo cp -ipl "$dst" "$src"
fi
done > fixup.sh
Это выведет набор команд mkdir/cp
которые вы можете запустить (fixup.sh
) в верхнем каталоге вашей копии в месте назначения. Убедитесь, что вывод скрипта будет делать то, что вам требуется. cp -ipl
не будет перезаписывать без запроса и будет копироваться с помощью жестких ссылок. Последующее rsync --delete ...
удалит старые файлы, предполагая, что требуется идентичная копия. Используйте rsync --dry-run ...
впоследствии, чтобы подтвердить степень любых оставшихся отличий.
(Можно использовать « mv -i
» вместо неразрушающего « cp -ipl
», сохраняя дублирование и очистку.)
Если у вас есть проблемные имена файлов / каталогов, вам нужно будет выполнить некоторую промежуточную обработку имен файлов или попробовать одно из решений здесь: https://unix.stackexchange.com/questions/6411/any-way-to-sync -directory-структура-когда-то-файлы-это-уже на обеих сторонах-
Обновление: если вы можете допустить взрыв в пунктуации, который проходит для командной строки sed
:
find . -type f -print0 | xargs -0 sha1sum |
sed -re $'s/(^[0-9a-z]*) /\\1__/;
s/ /\\\\x20/g; s/\'/\\\\\'/g;
s/(^[0-9a-z]*)__/\\1 /;
s/ (.*)$/ $\'\\1\'/g;'
Это будет обрабатывать пробелы и одинарные / двойные кавычки (хотя мы приближаемся к территории perl
для правильного поднятия тяжестей). Он использует конструкцию bash $''
для цитирования проблемных строк.