Come copiare-unire due directory?


112

Ho due directory di immagini e immagini2 con questa struttura in Linux:

/images/ad  
/images/fe  
/images/foo  

... e altre 4000 cartelle

e l'altro è come:

/images2/ad  
/images2/fe  
/images2/foo

... e altre 4000 cartelle

Ognuna di queste cartelle contiene immagini e i nomi delle directory in immagini e immagini2 sono esattamente gli stessi, tuttavia il loro contenuto è diverso. Quindi voglio sapere come posso copiare-unire le immagini di / images2 / ad in immagini / annuncio, le immagini di / immagini2 / pippo in immagini / pippo e così via con tutte le 4000 cartelle.


1
i file finali hanno lo stesso nome in entrambe le directory?
Simply_Me,

No ... ad esempio nelle immagini / annunci sono 1.jpg, 2.jpg e 3.jpg. Ma in images2 / ad sono 4.jpg e 5.jpg
ssierral

4
@AmirAliAkbari, non penso che sia un duplicato - l'altra domanda è fondamentalmente "Mv si fonde?" (risposta: no). Questa domanda riguarda come unire 2 gerarchie di directory.
Maxschlepzig,

Risposte:


173

Questo è un lavoro per rsync . Non vi è alcun vantaggio nel farlo manualmente con un loop di shell a meno che non si desideri spostare il file anziché copiarlo.

rsync -a /path/to/source/ /path/to/destination

Nel tuo caso:

rsync -a /images2/ /images/

(Nota la barra finale images2, altrimenti verrà copiata in /images/images2.)

Se in entrambe le directory esistono immagini con lo stesso nome, il comando sopra verrà sovrascritto /images/SOMEPATH/SOMEFILEcon /images2/SOMEPATH/SOMEFILE. Se si desidera sostituire solo i file più vecchi, aggiungere l'opzione -u. Se vuoi mantenere sempre la versione in /images, aggiungi l'opzione --ignore-existing.

Se vuoi spostare i file da /images2, con rsync, puoi passare l'opzione --remove-source-files. Quindi rsync copia tutti i file a turno e rimuove ogni file al termine. Questo è molto più lento dello spostamento se le directory di origine e di destinazione si trovano sullo stesso filesystem.


14
..aggiungi -P se vuoi vedere i progressi ..
Meetai.com

1
Vorrei aggiungere che non c'è alcun beneficio per utilizzando un ciclo di shell difficile qui, anche se non desidera spostare loro invece di loro, in questo caso basta usare la copia rsync, quindi rm -r /images.
Wildcard

1
Vorrei anche sottolineare che è importante includere le barre finali per ogni directory . Ad esempio, se hai semplicemente eseguito rsync -a images images2, copierà images2 in immagini invece di unirle.
Kyle Challis,

1
@ s3cur3 Oh. Da 2 a (implicito) 1. Non è intuitivo. Grazie, ho risolto la mia risposta.
Gilles

1
@MaxCoplan No. Rsync non è uno strumento interattivo.
Gilles,

43

La scelta migliore, come già pubblicata, è ovviamente rsync. Tuttavia anche l'unisono sarebbe un ottimo software per fare questo lavoro. Entrambi possono essere utilizzati in diversi sistemi operativi.

rsync

rsync si sincronizza in una direzione dalla sorgente alla destinazione. Pertanto la seguente dichiarazione

rsync -avh --progress Source Destination

sincronizza tutto, dalla sorgente alla destinazione . La cartella unita si trova in Destinazione .

-a significa "archivio" e copia tutto ricorsivamente dall'origine alla destinazione preservando quasi tutto.

-v fornisce più output ("dettagliato").

-h per la lettura umana.

--processo per mostrare quanto lavoro è stato fatto.

Se si desidera aggiornare solo la cartella di destinazione con i file più recenti dalla cartella di origine:

rsync -avhu --progress source destination

unisono

l'unisono si sincronizza in entrambe le direzioni. Pertanto la seguente dichiarazione

unison Source Destination

sincronizza entrambe le directory in entrambe le direzioni e infine l'origine è uguale a destinazione. È come fare rsync due volte dalla sorgente alla dest e viceversa.

Per usi più avanzati, consultare le pagine man o i seguenti siti Web:

  1. https://www.cis.upenn.edu/~bcpierce/unison/
  2. https://rsync.samba.org/

2
Voglio menzionare che il percorso corretto per la cartella dovrebbe essere con la barra finale alla fine rsync -avh --progress source/ destination/, altrimenti la cartella di origine verrà creata nella cartella di destinazione, almeno nel mio caso era così.
electroid

Questo funziona alla grande per me (con la barra finale nelle cartelle). Grazie!
Leopoldo Sanczyk,

5
for dir in images2/*; do mv "$dir"/* "images/$(basename "$dir")"; done

Scorri su tutto il contenuto images2dell'utilizzo di un glob espanso (per evitare problemi con l'analisi ls), quindi mvil contenuto di tali elementi alla voce corrispondente in images. Usa basenameper spogliare il piombo images2dal percorso traballante.


per favore aggiungi maggiori dettagli su ciò che fa il tuo comando in modo che sia utile anche per i futuri lettori :)
Ramesh,

1

@ inulinux12, puoi usare il seguente forloop di una riga dalla riga di comando:

$ for dir in images2/*; do mv "$dir"/* "${dir/2/}"; done

Questo sposterà tutti i file da images2a imagesnelle rispettive directory. Nota: questo presuppone che nessun file abbia lo stesso nome.

Per esempio:

Prima dell'esecuzione:

$ ls -R images*
images:
ad  adfoo  fe
images/ad:
jpg.1  jpg.2
images/adfoo:
jpg.7
images/fe:
jpg.5
images2:
ad  adfoo  fe
images2/ad:
jpg.3
images2/adfoo:
jpg.6
images2/fe:
jpg.4

Dopo l'esecuzione:

$ ls -R images*
images:
ad  adfoo  fe
images/ad:
jpg.1  jpg.2  jpg.3
images/adfoo:
jpg.6  jpg.7
images/fe:
jpg.4  jpg.5

3
Non analizzare l'output di ls. mywiki.wooledge.org/ParsingLs
Etan Reisner,

@EtanReisner Grazie per il suggerimento; sembra scenari piuttosto ristretti sebbene date le informazioni fornite nella domanda.
Simply_Me

2
@Simply_Me Se è vero che di solito andrà bene, non vuoi davvero farlo esplodere quando colpisci un caso su cui non stavi contando. Può causare problemi davvero gravi. Per non parlare del fatto che è abbastanza spesso (come in questo caso) quasi banalmente sostituibile con un semplice glob. Vedi la mia risposta come esempio di ciò.
Etan Reisner,

@Simply_Me Gli scenari includono nomi di file con spazi, il che è abbastanza comune per le immagini.
Gilles,

@Gilles e @Etan Reisner, grazie per l'input, lo apprezzo! Ho aggiornato e testato la mia risposta per utilizzare la sostituzione delle stringhe, ed è diventato più veloce dell'uso basenamein questa situazione particolare (non è necessario richiederlo basename). Grazie ancora per commenti costruttivi.
Simply_Me
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.