Ho due unità con gli stessi file, ma la struttura della directory è completamente diversa.
C'è un modo per "spostare" tutti i file sul lato di destinazione in modo che corrispondano alla struttura del lato di origine? Forse con uno script?
Ad esempio, l'unità A ha:
/foo/bar/123.txt
/foo/bar/234.txt
/foo/bar/dir/567.txt
Mentre l'unità B ha:
/some/other/path/123.txt
/bar/doo2/wow/234.txt
/bar/doo/567.txt
I file in questione sono enormi (800 GB), quindi non voglio ricopiarli; Voglio solo sincronizzare la struttura creando le directory necessarie e spostando i file.
Stavo pensando a uno script ricorsivo che avrebbe trovato ogni file di origine sulla destinazione, quindi lo avrebbe spostato in una directory corrispondente, creandolo se necessario. Ma — va oltre le mie capacità!
Un'altra soluzione elegante è stata data qui:
https://superuser.com/questions/237387/any-way-to-sync-directory-structure-when-the-files-are-already-on-both-sides /238086
Risposta accettata:
Andrò con Gilles e ti indicherò Unison come suggerito da hasen j. Unison era DropBox 20 anni prima di DropBox. Codice solido come una roccia che molte persone (me compreso) usano ogni giorno — molto utile da imparare. Comunque, join
ha bisogno di tutta la pubblicità che può ottenere 🙂
Questa è solo una mezza risposta, ma devo tornare al lavoro 🙂
Fondamentalmente, volevo dimostrare il poco noto join
utility che fa proprio questo:unisce due tabelle su un campo.
Innanzitutto, imposta un test case che includa i nomi dei file con spazi:
for d in a b 'c c'; do mkdir -p "old/$d"; echo $RANDOM > "old/${d}/${d}.txt"; done
cp -r old new
(modifica alcune directory e/o nomi di file in new
).
Ora, vogliamo costruire una mappa:hash -> filename per ogni directory e poi usare join
per abbinare i file con lo stesso hash. Per generare la mappa, inserisci quanto segue in makemap.sh
:
find "$1" -type f -exec md5 -r "{}" ;
| sed "s/([a-z0-9]*) ${1}/(.*)/1 "2"/"
makemap.sh
sputa un file con le righe del modulo, 'hash "filename"', quindi ci uniamo solo sulla prima colonna:
join <(./makemap.sh 'old') <(./makemap.sh 'new') >moves.txt
Questo genera moves.txt
che assomiglia a questo:
49787681dd7fcc685372784915855431 "a/a.txt" "bar/a.txt"
bfdaa3e91029d31610739d552ede0c26 "c c/c c.txt" "c c/c c.txt"
Il passo successivo sarebbe quello di fare effettivamente le mosse, ma i miei tentativi sono rimasti bloccati nel citare... mv -i
e mkdir -p
dovrebbe tornare utile.