Dati due alberi di directory, come posso sapere quali file differiscono per contenuto?


786

Se voglio trovare le differenze tra due alberi di directory, di solito eseguo solo:

diff -r dir1/ dir2/

Questo produce esattamente quali sono le differenze tra i file corrispondenti. Sono interessato a ottenere solo un elenco di file corrispondenti il ​​cui contenuto differisce. Supponevo che questo sarebbe semplicemente una questione di passaggio a un'opzione della riga di comando diff, ma non sono riuscito a trovare nulla nella pagina man.

Eventuali suggerimenti?



1
Per quanto riguarda una delle directory, come ottenere solo i file / directory che sono extra nell'altra?
Sandeepan Nath,

usa il dircmpcomando su unix (non su linux)
roblogic

Risposte:


1119

Hai detto Linux, quindi buona fortuna (almeno dovrebbe essere disponibile, non sono sicuro di quando è stato aggiunto):

diff --brief --recursive dir1/ dir2/ # GNU long options
diff -qr dir1/ dir2/ # common short options

Dovresti fare quello che ti serve.

Se vuoi vedere anche differenze per i file che potrebbero non esistere in nessuna delle due directory:

diff --brief --recursive --new-file dir1/ dir2/ # GNU long options
diff -qrN dir1/ dir2/ # common short options

12
Bello. Ma è più breve diff -qr dir1/ dir2/e la mia versione estesa adiff -qr dir1/ dir2/ | grep ' differ'
sobi3ch il

1
@skv perché? È lo stesso comando di risposta. Ho cambiato solo la --briefsua scorciatoia -q.
sobi3ch,

2
@skv Non è esattamente quello che ha posto la domanda originale, ma anche l'aggiornamento della risposta per adattarsi a questa domanda.
Mark Loeser,

3
@MikeMaxwell Deve esserlo --brief. -briefviene interpretato come -b -r -i -e -f, in altre parole, come un insieme di flag e non come una singola opzione.
daboross,

2
@daboross: wow, sto usando Unix / Linux da molto tempo e non ho mai capito che ci fosse quella distinzione tra '-' e '-'. (Non credo che "-" esistesse quando ho iniziato.) Grazie per la spiegazione!
Mike Maxwell,

287

Il comando che uso è:

diff -qr dir1/ dir2/

È esattamente lo stesso di Mark :) Ma la sua risposta mi ha infastidito perché usa diversi tipi di bandiere e mi ha fatto sembrare due volte. Usando le bandiere più dettagliate di Mark sarebbe:

diff  --brief --recursive dir1/ dir2/

Mi scuso per la pubblicazione quando l'altra risposta è perfettamente accettabile. Non riuscivo a fermarmi ... lavorando per essere meno pedante.


3
apprezzo totalmente la coerenza, ma non stare male; Ho votato anche la risposta di Mark;)
Gerard ONeill

10
.. ha senso che tu dia risposte diverse SOLO con un sapore diverso? IMHO no! Ha senso che tu combini entrambe le risposte a una risposta coerente? sì! ;)
sobi3ch,

1
Solo una domanda; cosa significa q? È un'abbreviazione di qualcosa? Non riesco a trovare alcuna logica dietro il q...
kramer65,

3
@ kramer65 - è lo stesso di "--brief", ma immagino ti chiederai perché q? Forse per una rapida? "-b" è preso da "ignora i cambiamenti nella quantità di spazio bianco" secondo la pagina man.
FPC,

4
@ kramer65 Credo che qsia per quiet, in genere significa meno prolisso.
Gogeta70,

105

Mi piace usare git diff --no-index dir1/ dir2/, perché può mostrare le differenze di colore (se hai quell'opzione impostata nella tua configurazione git) e perché mostra tutte le differenze in un output di paging lungo usando "less".


25
Neat. Chi avrebbe mai immaginato che Git potesse differire directory arbitrarie, non solo il repository rispetto ai suoi file?
Dan Dascalescu,

2
Perl script colordiff è molto utile qui, può essere utilizzato con svn e diff normale.
Felipe Alvarez,

4
Se si confrontano (come me) 2 dir come progetti / repository git separati, è necessario aggiungerne --no-indexaltri su stackoverflow.com/a/1792477/473390 . Ho aggiornato la risposta di @ alan-porter.
sobi3ch,

Mi piace questo, trovo anche che se aggiungi --name-status alla riga di comando, mostrerà solo l'elenco dei nomi di file con flag "M / A / D" per lo stato Modificato / Aggiunto / Eliminato.
martedì

Succede in modo che entrambe le directory contengano effettivamente la cartella .git, come posso escluderla dal confronto?
Muhamed Cicak,

35

Questi due comandi fanno sostanzialmente la cosa richiesta:

diff --brief --recursive --no-dereference --new-file --no-ignore-file-name-case /dir1 /dir2 > dirdiff_1.txt

rsync --recursive --delete --links --checksum --verbose --dry-run /dir1/ /dir2/ > dirdiff_2.txt

La scelta tra loro dipende dalla posizione di dir1 e dir2:

Quando le directory risiedono su due unità separate, diff supera le prestazioni di rsync. Ma quando le due directory confrontate si trovano sulla stessa unità, rsync è più veloce. È perché diff mette un carico quasi uguale su entrambe le directory in parallelo, massimizzando il carico sulle due unità.

rsync calcola i checksum in grossi pezzi prima di confrontarli effettivamente. Ciò raggruppa le operazioni di I / O in blocchi di grandi dimensioni e porta a un'elaborazione più efficiente quando le cose si svolgono su una singola unità.


3
rsync non è solo più veloce per i file su singole unità, ma consente anche di confrontare i file nei sottodir, ad esempio rsync --options /usr /bin /var /sbin /lib /old_rootconfronterà efficacemente l'attuale root /(specificando tutti i sottodir in esso) e /old_root(contenente ad esempio un backup precedente di /), che è qualcosa che diff -rpuò fare. E se supponi che i file con le stesse dimensioni, autorizzazioni e timestamp probabilmente non siano cambiati, tralasciando --checksumti fornirà un controllo estremamente rapido (se non così attraverso) di quali file potrebbero essere cambiati.
Matija Nalis,

1
Qual è lo scopo di --deletewith rsync?
Tom Hale,

2
Lo scopo di --delete è di eliminare i file esistenti nella directory di destinazione che non sono (più) presenti nella directory di origine
Thomas Munk

2
In questo caso (con la --dry-runbandiera) nulla viene veramente cancellato, rsyncstampa solo i file che sono in dir1 ma non in dir2
mata

11
Consiglio di mettere --dry-runsempre al primo posto per non dimenticarlo accidentalmente.
Dave Rager,

22

Meld è anche un ottimo strumento per confrontare due directory:

meld dir1/ dir2/

Combinazione ha molte opzioni per confrontare file o directory. Se due file differiscono, è facile accedere alla modalità di confronto dei file e vedere le differenze esatte.


2
Bello. Ho scritto un semplice script perl per eseguire il confronto sugli alberi, ma sto colpendo i limiti. Questo sembra essere il biglietto.
David Tonhofer,

L'unico problema è che non si presta allo scripting poiché è un'app grafica. Ma è bello se non ti dispiace la GUI! Grazie.
Decano

Trovo che melddiventa terribilmente lento se usato su grandi directory. C'è qualcosa che gestisce meglio le grandi directory?
Popup,

@Popup, non che io sappia. Potresti trovare nomi di file diversi con qualcosa del genere, però:find dir1 dir2 | cut -d/ -f2- | sort | uniq --unique
Alexander

1
@Alexander - In quel caso trovo che funzioni meld <(find dir1 -ls ) <(find dir2 -ls)abbastanza bene, usando la sostituzione del processo bash. (zsh =(command)funziona ancora meglio.)
Popup,

10

"Billings" (di freenode / # centos fame) del connazionale di Channel ha condiviso il suo metodo con me:

diff -Naur dir1/ dir2

Includere la barra finale della directory finale non ha importanza.

Inoltre, sembra che l' -uopzione non sia disponibile su alcune versioni precedenti / server di diff.

La differenza nelle differenze:

# diff -Nar /tmp/dir1 /tmp/dir2/
diff -Nar /tmp/dir1/file /tmp/dir2/file
28a29
> TEST

# diff -qr /tmp/dir1/ /tmp/dir2/
Files /tmp/dir1/file and /tmp/dir2/file differ

2
Questo è ciò --new-file/-Nche fa in modo che diff consideri i file mancanti come vuoti e --text/-ache li fa considerare tutti gli input binari come testo. Non vedo i lati positivi di questo particolare caso d'uso.
phk,

4

Diffoscope è un ottimo strumento diff directory basato su riga di comando.

Mi piace soprattutto che possa differire nei file:

Disimballerà ricorsivamente archivi di molti tipi e trasformerà vari formati binari in una forma più leggibile per confrontarli. Può confrontare due tarball, immagini ISO o PDF altrettanto facilmente.

Non solo ti dirà quali file differiscono, ma anche come differiscono.


4

Per trovare diff usa questo comando:

diff -qr dir1/ dir2/

-r diffonderà anche tutte le sottodirectory -q dice a diff di riferire solo quando i file differiscono.

diff  --brief dir1/ dir2/

--brief mostrerà i file esistenti nella directory.

O altro

possiamo usare Meld che mostrerà nella finestra grafica che è facile trovare la differenza.

meld  dir1/ dir2/

2
--briefe -qsono la stessa opzione. La tua affermazione fa sembrare che siano diversi ma non lo sono.
Elijah Lynn,

2

Puoi anche usare Rsynce find. Per find:

find $FOLDER -type f | cut -d/ -f2- | sort > /tmp/file_list_$FOLDER

Ma i file con gli stessi nomi e nelle stesse sottocartelle, ma con contenuti diversi, non verranno visualizzati negli elenchi.

Se sei un appassionato di grafica, è possibile controllare Meld che @Alexander menzionato. Funziona bene su Windows e Linux.


1

Per segnalare le differenze tra dirA e dirB, aggiornando / sincronizzando allo stesso tempo.

rsync -auv <dirA> <dirB>

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.