Najlepszy sposób na synchronizację plików - kopiuj tylko ISTNIEJĄCE pliki i tylko, jeśli NOWY jest niż docelowy

18

Synchronizuję lokalnie na Ubuntu 12.04. Pliki są zazwyczaj małymi plikami tekstowymi (kodami).

Chcę skopiować (zachowując stempel mtime) z sourcekatalogu, targetale chcę skopiować tylko wtedy, gdy plik target już istnieje i jest starszy niż ten w source.

Więc kopiuję tylko pliki, które są nowsze source, ale muszą one istnieć, targetinaczej nie zostaną skopiowane. ( sourcebędzie miał dużo więcej plików niż target.)

Będę kopiował z sourcewielu targetkatalogów. Wspominam o tym, jeśli ma to wpływ na wybór rozwiązania. Jednak mogę z łatwością uruchomić polecenie wiele razy, podając nowe za targetkażdym razem, jeśli jest to wymagane.

MountainX dla Moniki Cellio
źródło

Odpowiedzi:

29

Wierzę, że możesz rsyncto zrobić. Kluczową obserwacją będzie konieczność użycia przełączników --existingi --update.

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

Polecenie takie jak to by to zrobiło:

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

Przykład

Powiedzmy, że mamy następujące przykładowe dane.

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

Który wygląda następująco:

$ 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

Gdybym zsynchronizował te katalogi, nic by się nie wydarzyło:

$ 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

Jeśli jesteśmy touchplikiem źródłowym, aby był nowszy:

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

Kolejne uruchomienie rsyncpolecenia:

$ 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

Widzimy, że file3ponieważ jest nowszy i istnieje dst/, jest wysyłany.

Testowanie

Aby upewnić się, że wszystko działa, zanim wyciąć polecenia luźne, sugeruję używając innego rsync„s przełączników --dry-run. Dodajmy też kolejną, -vaby rsyncwynik był bardziej szczegółowy.

$ 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
źródło
Dziękuję Ci. Czy nie potrzebuję jeszcze kilku opcji rsync? Czytam stronę podręcznika. Wygląda na to, że mogę potrzebować to: rsync --archive --update --existing --whole-file --itemize-changes a/ b. A może większość z tych opcji jest niepotrzebna? (Dodałem cały plik, ponieważ są to głównie małe pliki tekstowe.)
MountainX dla Moniki Cellio
@ MountainX - dodaj tylko potrzebne opcje. Chciałbym zacząć -ato rozszerzeniem przełączników -rlptgoD.
slm
Pozwól mi to wyjaśnić. Jestem zdezorientowany --updatei --existing. Czy potrzebuję obu? Przetestowałem twoje rozwiązanie i wydaje się, że działa, ale nadal czuję się bezpieczniej --update.
MountainX dla Moniki Cellio
@MountainX - na pewno możesz go dodać, dodam go również do litery A.
slm