GNU/Linux >> Linux Esercitazione >  >> Linux

Un modo per sincronizzare la struttura delle directory quando i file sono già su entrambi i lati?

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.

Correlati:come glob ogni file nascosto tranne la directory corrente e principale?
Linux
  1. Come modificare l'estensione di più file?

  2. File di gatto con directory?

  3. Modo rapido per includere un percorso di directory quando si chiama Mv??

  4. Modo per dire a Logrotate di ignorare i file aperti?

  5. Contare il numero di file in una directory utilizzando C

C'è un modo per fare in modo che mv crei la directory in cui spostarsi se non esiste?

Quali sono le differenze tra i file .txt Linux e Windows (codifica Unicode)

Dov'è la directory temporanea in Linux?

Qual è il modo più efficiente per spostare un gran numero di file che risiedono in una singola directory?

Qual è il modo più veloce per rimuovere tutti i file e le sottocartelle in una directory?

Quali sono le implicazioni sulle prestazioni per milioni di file in un file system moderno?