Linux: confronta la struttura delle directory senza confrontare i file


55

Qual è il modo migliore e più semplice per confrontare due strutture di directory senza effettivamente confrontare i dati nei file? Funziona bene:

diff -qr dir1 dir2_

Ma è molto lento perché confronta anche i file. C'è un interruttore per diff o un altro semplice strumento di cli per fare questo?


Per "struttura di directory", intendi solo i percorsi di directory o i percorsi di entrambi i file di directory e non di directory?
intuito il

Sì, cartelle e file.
Giona,

1
In tal caso, dovresti rimuovere l' -type dopzione dalla risposta di @ slartibartfast, oppure dai un'occhiata alla mia risposta.
intuito il

Risposte:


36

Quanto segue (se si sostituisce la prima directory per directory1 e la seconda per directory2) dovrebbe fare quello che stai cercando e rapidamente:

find directory1 -type d -printf "%P\n" | sort > file1
find directory2 -type d -printf "%P\n" | sort | diff - file1

Il principio fondamentale è che stampa tutte le directory inclusi i percorsi delle sottodirectory relative alle directoryN di base.

Questo potrebbe cadere (produrre output strano) se si hanno ritorni a capo in alcuni dei nomi di directory ma non in altri.


Questo non va bene per me, perché se una directory contiene una cartella con poche migliaia di file, sono tutti elencati singolarmente, mentre diff -rqmostra solo che la directory root esiste in una e continua.
Chris Jefferson,

Come sottolineato (anni fa) da intuito, per rispondere alla domanda dei PO, il tipo d dovrebbe essere rimosso in modo che i file vengano considerati nel confronto e nelle directory
user2746401

Capisco e rispetto quella lettura della dichiarazione del problema. Non era la mia lettura al momento. Mi stai suggerendo di modificare la mia risposta per rispondere alla domanda aggiornata? Sto bene farlo se pensi che possa essere utile per alcune persone, e sto bene lasciando la soluzione e i commenti come sono adesso, il che sembra essere abbastanza efficace.
Slartibartfast,

34
vimdiff <(cd dir1; find . | sort) <(cd dir2; find . | sort)

ti darà una bella visualizzazione affiancata delle due gerarchie di directory con tutte le sezioni comuni piegate.


Questa soluzione fallisce in modo casuale. Quando vim legge (o rilegge) il descrittore di file temporaneo, è già sparito.
Denilson Sá Maia,

23

Di solito uso rsyncper questo compito:

rsync -nav --delete DIR1/ DIR2

FARE MOLTA ATTENZIONE utilizzare sempre la-n, alias--dry-run, l'opzione, o si sincronizza (cambiare il contenuto) delle directory.

Questo confronterà i file in base ai tempi e alle dimensioni di modifica dei file ... Penso che sia quello che vuoi davvero, o almeno non ti dispiace se lo fa? Ho avuto la sensazione che vuoi solo che accada più velocemente , non che tu ne abbia bisogno per ignorare la differenza tra il contenuto del file. Se vuoi che non elenchi file diversi con nomi identici, penso che l'aggiunta --ignore-existingdell'opzione lo farà.

Inoltre, tieni presente che il non mettere /a alla fine di DIR1farà comparare la directory DIR1 con il contenuto di DIR2.

L'output finisce per essere un po 'dettagliato, ma ti mostrerà quali file / directory differiscono. I file / directory presenti in DIR2e non in DIR1saranno preceduti dalla parola deleting.

Per alcune situazioni, la risposta di @ slartibartfast potrebbe essere più appropriata, sebbene sia necessario rimuovere l' -type dopzione per abilitare l'elenco dei file non di directory. rsyncsarà più veloce se hai un numero significativo di file / directory da confrontare.


Risposta eccellente. Nell'output di rsync è difficile notare il deleting...testo, ma è probabilmente uno dei modi migliori per confrontare i file mantenendo comunque la velocità. Le altre risposte qui sono più veloci quando non è richiesto il diffing dei file ... come nell'esempio di OP, ma mi piace molto questo.
Joel Mellon,

Questo è quello che stavo cercando. Avevo alcuni file con dimensioni diverse in una coppia enorme di alberi di directory e volevo sapere quali. Ciò ha raggiunto questo obiettivo in pochi secondi.
suprjami,

Forse è una buona idea eseguirlo con un utente che ha un accesso di sola lettura. Come sudo -u nobody rsync -nav --delete d1 d2purché le bandiere per "altri" consentano la lettura.
user1182474

Durante l'esecuzione di questa soluzione ho ottenuto "la creazione di un elenco di file ... fatto \ n inviato X byte ricevuti Y byte Z byte / sec dimensione totale è A speedup è B" (dove ho sostituito XYZAB per i numeri). Significa che tutto era identico? Dal momento che non ha menzionato nulla di più specifico? Grazie in anticipo
Scott H,

Per rispondere alla mia domanda, ho sperimentato l'aggiunta di file diversi a ciascuno di essi e sembra che nessun file / directory specifico menzionato nell'output significhi che sono tutti uguali.
Scott H,

18

Simile alla risposta ls ma se si installa tree allora è possibile

tree dir1 > out1
tree dir2 > out2
diff out1 out2

7
O per evitare i file tmp,diff <( tree dir1 ) <( tree dir2 )
Joel Mellon,

1
Consiglio di eseguire l'albero con la ibandiera, che non stampa le linee dell'albero ( tree -i dir1, ecc.). Se la struttura della directory è diversa in un punto, gli altri file che corrispondono possono avere più o meno |simboli nell'output dell'albero e diff prenderà quelle linee anche se i percorsi dei file sono identici.
askewchan,

2
diff <(albero -i dir1) <(albero -i dir2) è di gran lunga la risposta migliore. Sono tentato di sottovalutare tutte le risposte che suggeriscono diff o rsync poiché la domanda dice esplicitamente di NON leggere il contenuto del file. NOTA: il suggerimento di utilizzare due tubi richiede un uso attento degli spazi tra parentesi, seguire esattamente l'esempio. Ad esempio, per confrontare due volumi da 20 G dopo un backup, la risposta dell'albero ha richiesto circa 5 secondi. Gli altri hanno impiegato più di 20 minuti.
Jason Morgan,

3

Stavo solo cercando una soluzione per questo problema. La soluzione che mi è piaciuta di più è stata:

comm <(ls DIR1) <(ls DIR2)

Ti dà 3 colonne: 1 - file solo in DIR1, 2 - file solo in DIR2, 3 - file solo in DIR3 Per maggiori dettagli guarda questo post sul blog.


Dove è DIR3specificato? Tutto quello che vedo è DIR1e DIR2.
Michael Dorst,

L'ho provato e (da quello che posso dire) l'output è stato: tutti i file solo DIR1nella colonna 1 , tutti i file solo DIR2nella colonna 2 e tutti i file condivisi da entrambi nella colonna 3 . È utile, ma sai come si può eliminare la colonna 3 e lasciare solo le differenze? Ho molti file da ordinare e la maggior parte è identica. Non ho bisogno di vedere qual è la stessa cosa.
Michael Dorst,

1
Inoltre, ho scoperto che comm <(ls DIR1) <(ls DIR2)non ha funzionato in modo ricorsivo. Per quello che ho usato comm <(ls -R1 DIR1) <(ls -R1 DIR2). ls -Resegue la scansione ricorsiva delle directory e ls -1(si noti che si tratta di uno , non di una L ) fa lsstampare solo un nome file per riga.
Michael Dorst,

@Michael: comm -3(vedi man comm).
Zaz,

2
ls > dir1.txt

ls > dir2.txt

Quindi basta diff. Le due liste.


Sembra che l'OP voglia un'erarchia di percorsi. Ciò diffonderà tutti i file nella directory corrente. È discutibile, ma possibile, che vuole solo directory; potrebbe desiderare nomi di file piuttosto che il contenuto dei file.
intuito il

@intuited - hai ragione. L'ho letto male.
MDMarra,

2

Questa è la soluzione ottimale

diff --brief -r dir1 dir2

--brief switch indica solo se i file differiscono, non i dettagli della differenza.


1
L'OP ha già -qnella domanda, che è un alias per --brief. Questa risposta non fornisce nuove informazioni.
Michael Dorst,

1
OP non vuole il confronto dei contenuti del file. But it's really slow because it's comparing files too.
Joel Mellon,

1

usa "diff -qr" per ottenere i diversi file e poi filtra il confronto dei file con grep per ottenere solo i nomi dei file che sono solo in una delle directory.

diff -qr dir1 dir2 | grep -v "Files.*differ" 

1

Questo ha funzionato per la mia specifica necessità di trovare file mancanti negli alberi che dovrebbero corrispondere.

diff <( cd dir1; find * |sort ) <(cd dir2; find * | sort)

-3

Penso che solo rsync sia utile. perché?

diff è utile solo per strutture che mantengono file e directory. Diff non fornisce codici di uscita adeguati quando utilizziamo i collegamenti simbolici. In tale situazione, diff può restituire 2 codici di uscita, anche se src e dst sono identici (tempi, dimensioni, nomi, timestamp, softlink di puntamento ecc.).

dir, il filesystem non garantisce l'ordinamento dei file, anche se i contenuti della directory su src e dst sono identici. Forse dovresti filtrare l'output ls ordinandolo. Ma pure ls mostra solo i nomi dei nodi.

forse sarà utile lo script incluso diff, cmp, test -X per i tipi di nodo, ma ricorda il sovraccarico fatto da molte esecuzioni test / cmp. La sceneggiatura sarà molto lenta.

Come al solito, se vuoi ottenere informazioni semplici "dirs è / non è identico", dovresti usare rsync con l'opzione -n ​​(dry). Se vuoi trovare ciò che è diverso, usa il comando diff.


Vorrei sapere perché gli svantaggi?
Znik
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.