У меня два диска с одинаковыми файлами, но структура каталогов совершенно другая.
Есть ли способ «переместить» все файлы на стороне назначения, чтобы они соответствовали структуре на стороне источника? С сценарием что ли?
Например, диск A имеет:
/foo/bar/123.txt
/foo/bar/234.txt
/foo/bar/dir/567.txt
Принимая во внимание, что у диска B есть:
/some/other/path/123.txt
/bar/doo2/wow/234.txt
/bar/doo/567.txt
Эти файлы огромны (800 ГБ), поэтому я не хочу их заново копировать; Я просто хочу синхронизировать структуру путем создания необходимых каталогов и перемещения файлов.
Я думал о рекурсивном сценарии, который бы находил каждый исходный файл в месте назначения, а затем перемещал его в соответствующий каталог, создавая его при необходимости. Но - это за пределами моих способностей!
Другое элегантное решение было дано здесь: /superuser/237387/any-way-to-sync-directory-structure-when-the-files-are-already-on-both-sides/238086
Ответы:
Я пойду с Жилем и укажу на Унисон, как это предложил Хасен Дж . Унисон был DropBox за 20 лет до DropBox. Рок твердый код, который многие люди (включая меня) используют каждый день - очень стоит изучить. Тем не менее,
join
нужна вся реклама, которую он может получить :)Это только половина ответа, но я должен вернуться к работе :)
По сути, я хотел продемонстрировать малоизвестную
join
утилиту, которая делает именно это: объединяет две таблицы в каком-то поле.Сначала создайте тестовый набор, включающий имена файлов с пробелами:
(отредактируйте некоторые каталоги и / или имена файлов в
new
).Теперь мы хотим построить карту: хэш -> имя файла для каждого каталога, а затем использовать
join
для сопоставления файлов с одинаковым хешем. Чтобы сгенерировать карту, введите следующееmakemap.sh
:makemap.sh
выплевывает файл со строками вида 'hash "filename", поэтому мы просто присоединяемся к первому столбцу:Это генерирует
moves.txt
что выглядит так:Следующим шагом было бы на самом деле сделать ходы, но мои попытки застряли на цитировании ...
mv -i
иmkdir -p
должно пригодиться.источник
join
действительно интересно. Спасибо, что обратили на это мое внимание.join
входных данных?Есть утилита под названием unison:
http://www.cis.upenn.edu/~bcpierce/unison/
Описание с сайта:
Обратите внимание, что Unison обнаруживает перемещенные файлы при первом запуске, если хотя бы один из корней удален, поэтому, даже если вы синхронизируете локальные файлы, используйте в
ssh://localhost/path/to/dir
качестве одного из корней.источник
Используйте Unison как предложено hasen j . Я оставляю этот ответ в качестве потенциально полезного примера сценариев или для использования на сервере с установленными только базовыми утилитами.
Я предполагаю, что имена файлов уникальны во всей иерархии. Я также предполагаю, что ни одно имя файла не содержит символ новой строки и что деревья каталогов содержат только каталоги и обычные файлы.
Сначала соберите имена файлов на стороне источника.
Затем переместите файлы на место на стороне назначения. Сначала создайте сплющенное дерево файлов на стороне назначения. Используйте
ln
вместо,mv
если вы хотите сохранить жесткие ссылки в старой иерархии.Если некоторые файлы могут отсутствовать в месте назначения, создайте аналогично сплющенный файл
/A.staging
и используйте rsync для копирования данных из источника в место назначения.Теперь переименуйте файлы на место.
Эквивалентное:
Наконец, если вам нужны метаданные каталогов, вызовите rsync с уже установленными файлами.
Обратите внимание, что я не проверял фрагменты в этом посте. Используйте на свой риск. Пожалуйста, сообщите о любой ошибке в комментарии.
источник
Особенно, если текущая синхронизация будет полезна, вы можете попытаться выяснить git-annex .
Это относительно новый; Я не пытался использовать это сам.
Я могу предложить это, потому что он избегает хранения второй копии файлов ... это означает, что он должен помечать файлы как «только для чтения» («заблокированные»), как некоторые системы контроля версий не в Git.
Файлы идентифицируются по расширению sha256sum + (по умолчанию). Таким образом, он должен иметь возможность синхронизировать два репозитория с одинаковым содержимым файла, но с разными именами файлов, без необходимости выполнять запись (и по сети с низкой пропускной способностью, если это необходимо). Конечно, ему придется прочитать все файлы, чтобы проверить их.
источник
Как насчет чего-то вроде этого:
Это предполагает, что имена файлов, которые вы хотите синхронизировать, уникальны для всего диска: в противном случае это не может быть полностью автоматизировано (однако вы можете предложить пользователю выбрать, какой файл выбрать, если их больше).
Приведенный выше скрипт будет работать в простых случаях, но может потерпеть неудачу, если он
name
содержит символы, которые имеют особое значение для регулярных выражений.grep
В списке файлов также может занять много времени , если есть много файлов. Вы можете рассмотреть перевод этого кода на использование хеш-таблицы, которая будет отображать имена файлов в пути, например, в Ruby.источник
grep
линия? Он просто находит полный путь к соответствующему файлу вdstlist
?ln
этого создает символические ссылки. Вы можете использоватьmv
для перемещения файлов, но остерегайтесь перезаписи существующих. Кроме того, вы можете захотеть очистить пустые каталоги, если они есть, после удаления файлов. Да, этаgrep
команда ищет строку, которая заканчивается на имени файла, таким образом показывая полный путь к нему на целевом диске.Предполагая, что базовые имена файлов уникальны в деревьях, это довольно просто:
Если вы хотите очистить старые пустые каталоги, используйте:
источник
Я тоже столкнулся с этой проблемой. Решение на основе md5sum не работает для меня, потому что я синхронизирую свои файлы с
webdav
монтированием. Вычисление сумм md5sum в местеwebdav
назначения также будет означать большие файловые операции.Я сделал небольшой скрипт
reorg_Remote_Dir_detect_moves.sh
(на github), который пытается обнаружить наиболее перемещенные файлы, а затем создает новый временный shell-скрипт с несколькими командами для настройки удаленного каталога. Поскольку я занимаюсь только именами файлов, сценарий не является идеальным решением.В целях безопасности несколько файлов будут игнорироваться: A) Файлы с одинаковыми (одинаковыми начальными) именами на каждой стороне и B) Файлы, которые находятся только на удаленной стороне. Они будут проигнорированы и пропущены.
Пропущенные файлы будут обрабатываться вашим предпочтительным инструментом синхронизации (например
rsync, unison
, ...), который вы должны использовать после запуска временного shell-скрипта.Так может мой сценарий кому-нибудь пригодится? Если это так (чтобы было понятнее), есть три шага:
reorg_Remote_Dir_detect_moves.sh
(на github)/dev/shm/REORGRemoteMoveScript.sh
=> запустить его, чтобы сделать ходы (будет быстро при подключенииwebdav
)rsync, unison
, ...)источник
Вот моя попытка ответа. Как предупреждение, весь мой опыт написания сценариев происходит от bash, поэтому, если вы используете другую оболочку, имена команд или синтаксис могут отличаться.
Это решение требует создания двух отдельных скриптов.
Этот первый скрипт отвечает за фактическое перемещение файлов на целевом диске.
Второй сценарий создает файл карты md5, используемый первым сценарием, а затем вызывает первый сценарий для каждого файла на целевом диске.
По сути, два сценария аналогичны ассоциативному массиву
$md5_map_file
. Во-первых, все md5s для файлов на исходном диске вычисляются и сохраняются. С md5s связаны относительные пути от корня диска. Затем для каждого файла на целевом диске вычисляется md5. Используя этот md5, ищется путь к этому файлу на исходном диске. Затем файл на целевом диске перемещается в соответствии с путем к файлу на исходном диске.Есть несколько предостережений с этим сценарием:
источник
md5sum
похоже, не то, что здесь нужно использовать. (Кстати,rsync
есть режим, в котором он не вычисляет контрольные суммы.)