Помогите с командой script / rsync переместить файл со сравнением суммы md5 перед удалением исходного файла /

Ссылаясь на этот пост, чтобы найти и удалить дубликаты файлов на основе контрольной суммы , я хотел бы изменить подход для выполнения операции копирования с последующей проверкой целостности файла в конечном файле.

SOURCE = /path/to/Source DEST = /path/to/Destination # filecksums containing the md5 of the copied files declare -A filecksums for file in "$@" do [[ -f "$file" ]] || continue # Generate the checksum cksum=$(cksum &2 fi done 

Я хочу использовать результат сравнения контрольной суммы md5, чтобы разрешить rm -f исходного файла, только если контрольные суммы эквивалентны. Если есть разница, я хочу повторить результат и уйти. rsync может быть и другим вариантом, но я думаю, что у меня возникнут проблемы с принудительным сравнением контрольной суммы для локальной передачи файлов.

ОБНОВЛЕНИЕ Я рассмотрел использование rsync в ответ @Lucas. Похоже, что есть варианты для более стабильной передачи файлов с помощью чеков, а не массового mv /data1/* /data2/ и отчета о том, что было сделано, и удаления после проверки. Это может сузить определение, указанное членами сообщества.

    Реализация чего-то подобного может быть сложной в качестве первой попытки, если вы заботитесь о файлах и не хотите портить. Итак, вот несколько альтернатив написанию полного скрипта на bash. Это более или менее сложные командные строки (oneliners), которые могут помочь в вашей ситуации.

    В вашем вопросе есть одна неопределенность: хотите ли вы сравнить каждый файл в источнике с каждым файлом в dest или только те, которые имеют «совпадающие» имена файлов? (Это будет сравнение /path/to/src/a с /path/to/dest/a и /path/to/src/b с /path/to/dest/b но не /path/to/src/a с /path/to/dest/b и т. д.)

    Я предполагаю, что вы хотите сравнить только файлы с соответствующими путями!

    первая идея: diff

    Старый добрый diff может рекурсивно сравнивать каталоги. Также используйте параметр -q чтобы увидеть, какие файлы отличаются, а не как они отличаются.

     diff -r -q /path/to/source /path/to/dest 

    минусы

    • Это может занять много времени в зависимости от размера вашего жесткого диска.
    • Это не удаляет старые файлы.
    • Вывод я не легко разобрать

    профи

    • Это не удаляет файлы 🙂

    Поэтому после того, как вы вручную / визуально подтвердили, что нет никаких различий ни в каких файлах, которые вас интересуют, вы должны вручную удалить источник с помощью команды rm -rf /path/to/source .

    вторая идея: rsync (правка: сейчас это может быть лучше)

    rsync – мастер всех копирующих инструментов командной строки (по моему мнению;). Как уже упоминалось в комментариях к вашему вопросу, у него есть опция --checksum но у него также есть масса других опций. Он может передавать файлы с локального на удаленный, с удаленного на локальный и с локального на локальный. Одна из наиболее важных функций, на мой взгляд, заключается в том, что если вы введете правильные параметры, вы можете прервать выполнение команды и перезапустить ее (снова выполнить ту же самую командную строку), и она продолжит с того места, где она оставлена!

    Для вашей цели могут быть интересны следующие варианты:

    • -v : многословно, показать, что происходит, можно дать несколько раз, но обычно достаточно одного
    • -n : пробный запуск, очень важно проверять материал, но ничего не делать (в сочетании с -v ) !!
    • -c : использовать контрольную сумму, чтобы решить, что копировать
    • --remove-source-files : удаляет файлы, которые были успешно переданы (указано @ brawny84, я не знал об этом и не нашел его на странице руководства при первом прочтении)

    Таким образом, эта команда перезапишет все файлы в dest контрольная сумма отличается от соответствующего файла в source (соответствующем по имени).

      rsync -a -c -v --remove-source-files -n /path/to/source /path/to/dest rsync -a -c -v --remove-source-files /path/to/source /path/to/dest 

    профи

    • работает с контрольными суммами
    • имеет режим пробного запуска
    • фактически скопирует все отсутствующие файлы и файлы, которые отличаются от источника к месту назначения
    • можно прервать и перезапустить
    • имеет опцию исключения, чтобы игнорировать некоторые файлы в src, если вы не хотите копировать все файлы
    • может удалить переданные исходные файлы

    минусы

    • ??

    третья идея: fdupes

    Программа fdupes я разработал, чтобы fdupes список дубликатов файлов. Он проверяет md5sums по умолчанию.

    профи

    • он использует MD5 для сравнения файлов
    • у него есть опция --delete для удаления одного из дубликатов

    минусы

    • он сравнивает каждый файл с любым другим файлом, поэтому, если в самом Dest есть дублирующиеся файлы, он также перечисляет их
    • Режим удаления кажется интерактивным, вы должны подтвердить для каждого набора одинаковых файлов, что может оказаться невозможным для больших деревьев каталогов
    • неинтерактивный режим удалит все файлы, кроме первого, из каждого набора равных файлов. Но я понятия не имею, какой первый файл (в исходном или в Dest?)

    Последняя идея: пройти через процесс написания и отладки собственного сценария оболочки

    Я бы начал с чего-то вроде этого, если это нужно сделать вручную. Я не проверял это, попробуйте сначала с помощью ls и попытайтесь выяснить, будет ли это что-то тормозить !!

     #!/bin/bash # first require that the source and dest dirs # are given as arguments to the script. src=${1:?Please give the source dir as first argument} dest=${2:?Please give the destination dir as second argument} # go to the source directory cd "$src" # This assumes that there are no newlines in filenames! # first find all plain files in the current dir # (which should be $src) # then use xargs to hand the filenames to md5sum # pipe the md5 sums into a subshell # go to the dest in the subshell # read the md5sums from stdin and use md5sum -c to check them # After the subshell filter lines to only keep those that end in "OK" # and at the same time remove the "OK" stuff after the file name # use xargs to hand these file names to ls or rm. find . -type f | \ xargs md5sum | \ ( cd "$dest" && md5sum -c ) | \ sed -n 's/: OK$//p' | \ xargs ls 

    ls в последней строке должен перечислить все файлы, которые прошли проверку. Если вы замените его на rm они будут удалены из исходного каталога (текущего каталога после cd "$src" ).