Melhor maneira de sincronizar arquivos - copie apenas arquivos EXISTENTES e somente se MAIS NOVO que o destino

18

Estou fazendo essa sincronização localmente no Ubuntu 12.04. Os arquivos geralmente são pequenos arquivos de texto (código).

Desejo copiar (preservando o carimbo do mtime) do sourcediretório para, targetmas só quero copiar se o arquivo target já existir e for mais antigo que o source.

Estou copiando apenas os arquivos mais recentes source, mas eles devem existir targetou não serão copiados. ( sourceterá muito mais arquivos que target.)

Na verdade, eu vou copiar sourcepara vários targetdiretórios. Menciono isso no caso de afetar a escolha da solução. No entanto, posso executar meu comando facilmente várias vezes, especificando o novo a targetcada vez, se é isso que é necessário.

MountainX para Monica Cellio
fonte

Respostas:

29

Eu acredito que você pode usar rsyncpara fazer isso. A observação principal seria a necessidade de usar as opções --existinge --update.

        --existing              skip creating new files on receiver
        -u, --update            skip files that are newer on the receiver

Um comando como este faria isso:

$ rsync -avz --update --existing src/ dst

Exemplo

Digamos que temos os seguintes dados de amostra.

$ mkdir -p src/; touch src/file{1..3}
$ mkdir -p dst/; touch dst/file{2..3}
$ touch -d 20120101 src/file2

Com a seguinte aparência:

$ ls -l src/ dst/
dst/:
total 0
-rw-rw-r--. 1 saml saml 0 Feb 27 01:00 file2
-rw-rw-r--. 1 saml saml 0 Feb 27 01:00 file3

src/:
total 0
-rw-rw-r--. 1 saml saml 0 Feb 27 01:00 file1
-rw-rw-r--. 1 saml saml 0 Jan  1  2012 file2
-rw-rw-r--. 1 saml saml 0 Feb 27 01:00 file3

Agora, se eu fosse sincronizar esses diretórios, nada aconteceria:

$ rsync -avz --update --existing src/ dst
sending incremental file list

sent 12 bytes  received 31 bytes  406.00 bytes/sec
total size is 0  speedup is 0.00

Se tivermos touchum arquivo de origem para que seja mais recente:

$ touch src/file3 
$ ls -l src/file3
-rw-rw-r--. 1 saml saml 0 Feb 27 01:04 src/file3

Outra execução do rsynccomando:

$ rsync -avz --update --existing src/ dst
sending incremental file list
file3

sent 115 bytes  received 31 bytes  292.00 bytes/sec
total size is 0  speedup is 0.00

Podemos ver que file3, como é mais recente e existe dst/, é enviado.

Teste

Para garantir que as coisas funcionem antes de você soltar o comando, sugiro usar outro dos rsyncinterruptores --dry-run,. Vamos adicionar outro -vtambém, para que rsynca saída seja mais detalhada.

$ rsync -avvz --dry-run --update --existing src/ dst 
sending incremental file list
delta-transmission disabled for local transfer or --whole-file
file1
file2 is uptodate
file3 is newer
total: matches=0  hash_hits=0  false_alarms=0 data=0

sent 88 bytes  received 21 bytes  218.00 bytes/sec
total size is 0  speedup is 0.00 (DRY RUN)
slm
fonte
Obrigado. Não preciso de mais algumas opções de rsync? Estou lendo a página de manual. Parece que eu poderia precisar o seguinte: rsync --archive --update --existing --whole-file --itemize-changes a/ b. Ou a maioria dessas opções é desnecessária? (Eu adicionei arquivo inteiro porque estes são na sua maioria pequenos arquivos de texto.)
MountainX para Monica Cellio
@MountainX - adicione apenas as opções necessárias. Eu começaria com -aum superconjunto de opções -rlptgoD.
slm
Deixe-me esclarecer isso. Estou confuso sobre --updatee --existing. Preciso dos dois? Testei sua solução e ela parece funcionar, mas ainda me sinto mais segura em adicionar --update.
MountainX para Monica Cellio
@ MountainX - com certeza você pode adicioná-lo, eu também o colocarei no A.
slm