Ajuda com o comando script / rsync para mover o arquivo com a comparação de soma md5 antes de excluir o arquivo de origem / [closed]

1

Referenciando este postar para encontrar e excluir arquivos duplicados com base na soma de verificação , gostaria de modificar a abordagem para executar uma operação de cópia seguida de uma verificação de integridade de arquivo no arquivo de destino.

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 <"$file" | tr ' ' _)

    # Can an exact duplicate be found in the destination directory?
    if [[ -n "${filecksums[$cksum]}" ]] && [[ "${filecksums[$cksum]}" != "$file" ]]
    then
        rm -f "$file"
    else
        echo " '$file' is not in '$DEST'" >&2
    fi
done

Eu quero usar o resultado da comparação de soma de verificação md5 para permitir rm -f do arquivo de origem somente se as somas de verificação forem equivalentes. Se houver diferença, quero repetir o resultado e escapar. rsync pode ser outra opção, mas acho que teria problemas ao forçar uma comparação de soma de verificação para a transferência de arquivo local-local.

UPDATE Eu olhei para o uso do rsync per the @ Lucas's answer. Parece que há opções para transferir arquivos de forma mais estável com as verificações, em vez de uma% em massamv /data1/* /data2/ e relatar o que foi feito e excluir após uma verificação. Isso pode restringir a definição conforme indicado pelos membros da comunidade.

    
por brawny84 10.07.2018 / 20:25

1 resposta

1

Implementar algo assim pode ser difícil como uma primeira tentativa, se você se importa com os arquivos e não quer estragar. Então, aqui estão algumas alternativas para escrever um script completo no bash. Estas são linhas de comando mais ou menos complexas (oneliners) que podem ajudar na sua situação.

Há uma incerteza em sua pergunta: você quer comparar cada arquivo na origem com todo arquivo em dest ou somente aqueles com nomes de arquivos "correspondentes"? (Isso seria comparar /path/to/src/a com /path/to/dest/a e /path/to/src/b com /path/to/dest/b , mas não /path/to/src/a com /path/to/dest/b e assim por diante)

Suponho que você queira apenas comparar arquivos com caminhos correspondentes !!

primeira ideia: diff

O bom e velho diff pode comparar diretórios recursivamente. Também use a opção -q para ver quais arquivos diferem e não como eles diferem.

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

cons

  • Isso pode levar um tempo longo dependendo do tamanho do seu disco rígido.
  • Isso não exclui os arquivos antigos.
  • A saída não é facilmente analisável

pros

  • Isso não exclui nenhum arquivo:)

Então, após confirmar manualmente / visualmente que não há diferenças em nenhum arquivo de seu interesse, você deve excluir manualmente a origem com rm -rf /path/to/source .

segunda ideia: rsync (editar: isso pode ser o melhor agora)

rsync é o mestre de todas as ferramentas de linha de comando de cópia (na minha opinião). Como mencionado nos comentários da sua pergunta, ele tem uma opção --checksum , mas também tem um bulkload de outras opções. Pode transferir arquivos de local para remoto, de remoto para local e de local para local. Uma das características mais importantes, na minha opinião, é que se você der as opções corretas, você pode abortar e reiniciar o comando (executar a mesma linha de comando novamente) e continuará de onde saiu!

Para o seu objetivo, as seguintes opções podem ser interessantes:

  • -v : verbose, mostre o que acontece pode ser dado várias vezes, mas normalmente uma é suficiente
  • -n : corrida seca, muito importante para testar coisas, mas não faça nada (combine com -v ) !!
  • -c : use a soma de verificação para decidir o que deve ser copiado
  • --remove-source-files : remove arquivos que foram transferidos com sucesso (apontado por @brawny84, eu não sabia e não o encontrei na página man na minha primeira leitura)

Portanto, este comando sobrescreverá todos os arquivos em dest que tenham uma soma de verificação diferente do arquivo correspondente em source (correspondente por nome).

 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

pros

  • funciona com somas de verificação
  • tem um modo de execução a seco
  • copia todos os arquivos e arquivos ausentes que diferem da origem para o destino
  • pode ser interrompido e reiniciado
  • tem uma opção de exclusão para ignorar alguns arquivos em src se você não quiser copiar todos os arquivos
  • pode excluir arquivos de origem transferidos

cons

  • ??

terceira ideia: fdupes

O programa fdupes Eu projetei listar arquivos duplicados. Ele verifica o md5sums por padrão.

pros

  • usa o md5 para comparar arquivos
  • tem uma opção --delete para excluir uma das duplicatas

cons

  • compara o arquivo each com todos os outros arquivos , assim, se houver arquivos duplicados dentro do próprio destino, ele também os listará
  • o modo de exclusão parece ser interativo, você precisa confirmar para cada conjunto de arquivos iguais que podem não ser viáveis para árvores de diretórios grandes
  • o modo não interativo excluirá todos os arquivos, exceto o primeiro, de cada conjunto de arquivos iguais. Mas não tenho idéia do que é o primeiro arquivo (na origem ou no destino?)

última ideia: passe pela dor de escrever e depurar seu próprio script de shell

Eu começaria com algo assim se tivesse que ser feito manualmente. Eu não testei isso, tente com o ls primeiro e tente descobrir se ele irá quebrar alguma coisa !!

#!/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

O ls na última linha é para listar todos os arquivos que passaram na verificação. Se você substituí-lo por rm , eles serão removidos do diretório de origem (o diretório atual após o cd "$src" ).

    
por 10.07.2018 / 22:05