confronta 2 directory e copia le differenze in una terza directory


32

Con Ubuntu 12.04, voglio confrontare 2 directory, dire cartella1 / e cartella2 / e copiare tutti i file che sono diversi da cartella3 /. Esistono anche file nidificati, quindi anche le sottodirectory corrispondenti devono essere copiate

C'è un singolo comando che mi potrebbe aiutare? Posso ottenere l'elenco completo dei file modificati in esecuzione:

rsync -rcnC --out-format="%f" folder1/ folder2/

Ma rsync non sembra avere la possibilità di "esportare" questi file in una directory di destinazione diversa. Posso reindirizzare l'elenco su cp o su qualche altro programma, in modo che i file vengano copiati, mentre anche le directory vengono create? Ad esempio, ci ho provato

rsync -rcnC --out-format="%f" folder1/ folder2/ | xargs cp -t folder3/

ma ciò non preserverebbe anche le directory, semplicemente copierebbe tutti i file all'interno della cartella3 /


Probabilmente diff -qrawkrsync
userei

come dovrei usare rsync con l'elenco?
periklis,

Avrei eseguito un for-loop o avrei usato l' rsync --include-from=FILEopzione.
ewwhite

(Non essere pigro ...) Ma la soluzione rsync di seguito è elegante.
ewwhite,

Risposte:


38

Usa --compare-dest.

Dalla pagina man:

--compare-dest = DIR - Questa opzione indica a rsync di utilizzare DIR sul computer di destinazione come gerarchia aggiuntiva per confrontare i file di destinazione con i trasferimenti (se i file mancano nella directory di destinazione). Se viene trovato un file in DIR identico al file del mittente, il file NON verrà trasferito nella directory di destinazione. Ciò è utile per creare un backup sparso di soli file che sono stati modificati da un backup precedente.

controlla prima la sintassi con --dry-run

rsync -aHxv --progress --dry-run --compare-dest=folder2/ folder1/ folder3/

Quindi, una volta che sei soddisfatto dell'output:

rsync -aHxv --progress  --compare-dest=folder2/ folder1/ folder3/

questo link ha una buona spiegazione dell'ambito --compare-dest.


1
Grazie per questo, non avevo capito la spiegazione della pagina man di questo parametro. Per chiunque fosse interessato, l'ho fatto conrsync -rcC --compare-dest=folder2/ folder1/ folder3/
periklis

breve nota per gli utenti OsX. Ho rsync version 3.1.1 protocol version 31sul mio locale e rsync non capisce i ~/percorsi per --compare-destparam.
Jevgeni Smirnov,

4
Per me, ha --compare-destrichiesto un percorso assoluto.
Palswim,

Non ha funzionato per me con le opzioni dell'autore o dell'OP. Vale a dire che genera un fonts/Makefile.infile, che è identico in entrambi folder2e folder1dirs.
Hi-Angel,

3

Questo piccolo script dovrebbe funzionare:

folder1="firsts_folder/"
folder2="second_folder/"
folder3="target_folder"
for x in `rsync -rcnC --out-format="%n"  $folder1 $folder2`
    do
        if [ -d "$folder1/$x" ]; then
            mkdir -p "$folder3/$x"
        else
            cp -frv $folder1/$x $folder3/$x
        fi
done

Ma penso anche che analizzare l'output di diff -qr sarebbe una soluzione migliore perché ti dà il percorso e il nome per ogni file in modo coerente.

MODIFICARE

Questo sarebbe un comando, il tuo comando leggermente modificato. Ma creerà folder1sotto il folder3. E non funziona con percorsi completi, ma anche lo script sopra non funziona con percorsi completi.

rsync -rcnC --out-format="\"%f\"" folder1/ folder2/ | xargs cp --parents -rfvt folder3/

Ho usato \"a rsyncfarlo funzionare con i file e le directory che contiene spazi vuoti. Testato su Ubuntu 10.04. Spero che sia d'aiuto.


grazie per questo, avevo sperato che esistesse un solo comando
periklis,

2
rsync -rcnC --out-format="%f" . ../folder2/ |xargs cp --parents -rt ../folder3/

Questa è la forma più semplice che potrei trovare, se sei disposto a scendere folder1prima di emettere il comando.

Questa è l' opzione più lenta , ma credo che soddisfi i tuoi requisiti e potrebbe essere eseguita utilizzando nomi di directory non relativi:

rsync -rcnC --out-format="%n" folder1/ folder2/ |grep -vP "/$" |xargs -I{} rsync -R folder1/./{} folder3/

Ho lasciato da solo il tuo rsynccomando originale , perché hai detto che ti stava dando l'elenco di file corretto (e i miei file di test sono ovviamente diversi dai tuoi, quindi non potrei dire con certezza che avrei ottenuto l'elenco di file corretto se avessi sbagliato con esso).

L' grepè lì per rimuovere i nomi di directory dall'uscita di rsync.

L'output di grepviene quindi reindirizzato a un altro rsyncutilizzando xargs. Nel parametro folder1/./{}l'extra ./è usato per dire a rsync di creare le relative directory iniziando ./{}, ignorando folder1/. In altre parole, evita di creare folder3/folder1/.

Sono stato in grado di testarlo solo su CentOS 6.4, ma AFAIK dovrebbe funzionare allo stesso modo in Ubuntu 12.04.

EDIT: dovrei notare che la risposta di Smithian è senza dubbio migliore, ma volevo fare una pugnalata nel farlo con il tuo rsynccomando originale in tatto poiché ti stava dando l'output desiderato.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.