Linux - Copie apenas arquivos novos e maiores

2

Eu tenho dois diretórios com milhares de arquivos que contêm mais ou menos os mesmos arquivos.

Como posso copiar todos os arquivos de dirA para dirB que não estão em dirB ou se o arquivo existe em dirB somente sobrescreva se for menor.

Eu sei que há muitos exemplos para timestamp diferente ou tamanho de arquivo diferente, mas eu só quero substituir se o arquivo de destino for menor e sob nenhuma circunstância se for maior.

Antecedentes do meu problema:
Eu criei um dynmap no meu Minecraft Server, mas alguns dos blocos estão ausentes ou corrompidos. Então fiz a renderização novamente em outra máquina com uma CPU mais rápida e copiei todos os novos arquivos renderizados (~ 50 GB / 6.000.000 ~ 4-10 KB PNGs) no meu servidor. Depois disso, notei que também há arquivos corrompidos em minha nova renderização.

left: renderização antiga, direita: nova renderização

Por isso não quero sobrescrever todos os arquivos, mas apenas os que são maiores (os corrompidos carregam menos dados e são menores).

    
por das Keks 03.02.2017 / 12:58

3 respostas

2

Pode ser um caminho sujo, mas espero que seja o que você está procurando

#!/bin/bash

### Purpose:
# Copy huge amount of files from source to destination directory only if
# destination file is smaller in size than in source directory
###

src='./d1' # Source directory
dst='./d2' # Destination directory

icp() {
  f="${1}";
  [ -d "$f" ] && {
    [ ! -d "${dst}${f#$src}" ] && mkdir -p "${dst}${f#$src}";
    return
  }

  [ ! -f "${dst}/${f#$src/}" ] && { cp -a "${f}" "${dst}/${f#$src/}"; return; }
  fsizeSrc=$( stat -c %s "$f" )
  fsizeDst=$( stat -c %s "${dst}/${f#$src/}" )
  [ ${fsizeDst} -lt ${fsizeSrc} ] && cp -a "${f}" "${dst}/${f#$src/}"
}

export -f icp
export src
export dst

find ${src} -exec bash -c 'icp "$0"' {} \;
    
por 04.02.2017 / 00:22
1

Você pode usar o comando rsync

Sintaxe:

-a = archive mode
-v = increase verbosity
-z = compress file data during the transfer
--progress = show progress during transfer

rsync -avz --progress <source path> <destination path>

você pode usar --delete para excluir arquivos estranhos do diretório de destino

rsync -avz --delete --progress <source path> <destination path>

para que seu comando seja:

rsync -avz --delete --progress dirA dirB
    
por 03.02.2017 / 13:51
0

Meu problema foi semelhante. Eu queria sincronizar arquivos de uma pasta remota para uma local, mas apenas copiar os arquivos remotos que eram maiores do que os arquivos locais correspondentes.

Minha solução alternativa com o rsync era assim, o que, na verdade, era uma frase simples:

for x in $(ls -1 home/me/local/folder/*)
do
    eachsize=$(stat -c "%s")
    rsync -avz --progress --max-size=${eachsize} remote:/home/you/folder/${x} .
done

Eu acho que você pode entender, já que os nomes de arquivos são os mesmos entre as duas pastas, eu passo por cada um na pasta local e mantenho seu tamanho, então eu coloco como um limite se o rsync deve copiar ou não o arquivo remoto com o mesmo nome mas tamanho diferente.

    
por 04.09.2017 / 14:48