Biorąc pod uwagę dwa drzewa katalogów, jak mogę dowiedzieć się, które pliki różnią się zawartością?

786

Jeśli chcę znaleźć różnice między dwoma drzewami katalogów, zwykle po prostu wykonuję:

diff -r dir1/ dir2/

To pokazuje dokładnie, jakie są różnice między odpowiednimi plikami. Chcę tylko uzyskać listę odpowiednich plików, których zawartość różni się. Zakładałem, że będzie to po prostu kwestia przekazania opcji wiersza poleceń diff, ale nie mogłem znaleźć niczego na stronie podręcznika.

Jakieś sugestie?

Mansoor Siddiqui
źródło
1
W odniesieniu do jednego z katalogów, jak uzyskać tylko pliki / katalogi, które są dodatkowe w drugim?
Sandeepan Nath,
użyj dircmpkomendy na
Uniksie

Odpowiedzi:

1118

Powiedziałeś Linux, więc masz szczęście (przynajmniej powinien być dostępny, nie jestem pewien, kiedy został dodany):

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

Powinieneś zrobić to, czego potrzebujesz.

Jeśli chcesz zobaczyć różnice w plikach, które mogą nie istnieć w żadnym z katalogów:

diff --brief --recursive --new-file dir1/ dir2/ # GNU long options
diff -qrN dir1/ dir2/ # common short options
Mark Loeser
źródło
12
Miły. Ale krótsza jest diff -qr dir1/ dir2/i moja rozszerzona wersja dodiff -qr dir1/ dir2/ | grep ' differ'
sobi3ch
1
@skv dlaczego? To to samo polecenie co odpowiedź. Zmieniłem tylko --briefskrót -q.
sobi3ch
2
@skv Niezupełnie to, co zadało pierwotne pytanie, ale aktualizacja odpowiedzi w celu uwzględnienia tego pytania.
Mark Loeser,
3
@MikeMaxwell To musi być --brief. -briefjest interpretowany jako -b -r -i -e -f, innymi słowy, jako zestaw flag, a nie jako pojedyncza opcja.
daboross
2
@daboross: wow, od dłuższego czasu używam Uniksa / Linuksa i nigdy nie zdawałem sobie sprawy, że istnieje różnica między „-” a „-”. (Nie sądzę, że „-” istniało, kiedy zaczynałem.) Dzięki za wyjaśnienie!
Mike Maxwell
287

Polecenie, którego używam to:

diff -qr dir1/ dir2/

To jest dokładnie to samo, co Mark :) Ale jego odpowiedź mnie niepokoiła, ponieważ używa różnych rodzajów flag i sprawiła, że ​​spojrzałem dwa razy. Przy użyciu bardziej szczegółowych flag Marka byłoby to:

diff  --brief --recursive dir1/ dir2/

Przepraszam za opublikowanie, gdy druga odpowiedź jest całkowicie do przyjęcia. Nie mogłem się powstrzymać ... pracując nad byciem mniej pedantycznym.

FPC
źródło
3
całkowicie doceniaj spójność - ale nie czuj się źle; Głosowałem również za odpowiedzią Marka;)
Gerard ONeill
10
... czy to ma sens, aby tu wstawiać różne odpowiedzi, JUST tylko inny smak? IMHO nie! Czy ma sens łączenie obu odpowiedzi w jedną spójną? tak! ;)
sobi3ch
1
Tylko pytanie; co oznacza qskrót Czy to skrót czegoś? Nie mogę znaleźć żadnej logiki za q..
kramer65
3
@ kramer65 - to samo co „--brief”, ale myślę, że zastanawiasz się, dlaczego q? Może za szybko? „-b” jest przejmowane przez „ignoruj ​​zmiany w ilości białych znaków” zgodnie ze stroną podręcznika.
FPC
3
@ kramer65 Wierzę, że qto jest quiet, co ogólnie oznacza mniej gadatliwy.
Gogeta70,
105

Lubię używać git diff --no-index dir1/ dir2/, ponieważ może pokazywać różnice w kolorze (jeśli masz tę opcję ustawioną w konfiguracji git) i ponieważ pokazuje wszystkie różnice w długim wydruku stronicowanym przy użyciu „mniej”.

Alan Porter
źródło
25
Schludny. Kto by pomyślał, że git może różnicować dowolne katalogi, a nie tylko repozytorium z jego plikami?
Dan Dascalescu
2
Colordiff skryptowy Perla jest tutaj bardzo przydatny, można go używać z svn i normalnym diff.
Felipe Alvarez
4
Jeśli porównujesz (jak ja) 2 katalogi jako osobne projekty / repozytorium git, musisz dodać --no-indexwięcej na stackoverflow.com/a/1792477/473390 . Zaktualizowałem odpowiedź @ alan-porter.
sobi3ch
Podoba mi się ten, znajduję również, że jeśli dodasz --name-status do wiersza poleceń, po prostu pokaże listę nazw plików z flagami „M / A / D” dla statusu Zmodyfikowany / Dodany / Usunięte.
gzh
Zdarza się, że oba katalogi faktycznie zawierają folder .git, jak mogę wykluczyć go z porównania?
Muhamed Cicak
35

Te dwa polecenia wykonują w zasadzie to, o co proszono:

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

Wybór między nimi zależy od lokalizacji katalogu 1 i katalogu 2:

Gdy katalogi znajdują się na dwóch osobnych dyskach, diff przewyższa rsync. Ale gdy dwa porównywane katalogi znajdują się na tym samym dysku, rsync jest szybszy. Jest tak, ponieważ diff nakłada prawie równe obciążenie na oba katalogi równolegle, maksymalizując obciążenie dwóch dysków.

rsync oblicza sumy kontrolne w dużych porcjach przed ich faktycznym porównaniem. To grupuje operacje we / wy w duże porcje i prowadzi do bardziej wydajnego przetwarzania, gdy rzeczy mają miejsce na jednym dysku.

CodeBug
źródło
3
rsync jest nie tylko szybszy w przypadku plików na pojedynczych dyskach, ale także pozwala na porównywanie plików w podkatalogach, na przykład rsync --options /usr /bin /var /sbin /lib /old_rootskutecznie porównuje bieżący katalog główny /(poprzez określenie w nim wszystkich podkatalogów) i /old_root(zawiera na przykład niektóre starsze kopie zapasowe /), co jest czymś, co diff -rmoże tak. A jeśli przyjmiesz, że pliki o tym samym rozmiarze, uprawnieniach i znacznikach czasu prawdopodobnie się nie zmieniły, pominięcie --checksumzapewni Ci niezwykle szybkie (jeśli nie tak do końca) sprawdzenie, które pliki mogły ulec zmianie.
Matija Nalis,
1
Jaki jest cel --deletez rsync?
Tom Hale,
2
Celem --delete jest usunięcie istniejących plików z katalogu docelowego, których nie ma (już) w katalogu źródłowym
Thomas Munk
2
W tym przypadku (z --dry-runflagą) tak naprawdę nic nie jest usuwane, rsyncdrukowane są tylko te pliki, które znajdują się w katalogu 1, ale nie w katalogu 2
mata
11
Polecam stawianie --dry-runzawsze na pierwszym miejscu, aby nie zapomnieć o tym przypadkowo.
Dave Rager
22

Meld jest także doskonałym narzędziem do porównywania dwóch katalogów:

meld dir1/ dir2/

Meld ma wiele opcji porównywania plików lub katalogów. Jeśli dwa pliki różnią się, łatwo przejść do trybu porównywania plików i zobaczyć dokładne różnice.

Alexander
źródło
2
Miły. Napisałem prosty skrypt perla do przeprowadzania porównań między drzewami, ale przekraczam ograniczenia. To wydaje się być biletem.
David Tonhofer
Jedynym problemem jest to, że nie nadaje się do pisania skryptów, ponieważ jest to aplikacja graficzna. Ale to miłe, jeśli nie przeszkadza ci GUI! Dzięki.
DeanM,
Uważam, że meldstaje się to okropnie powolne, jeśli jest używane w dużych katalogach. Czy jest coś, co lepiej radzi sobie z dużymi katalogami?
Popup
@Pupup, nie o tym wiem. Można jednak znaleźć różne nazwy plików z czymś takim:find dir1 dir2 | cut -d/ -f2- | sort | uniq --unique
Alexander
1
@Alexander - W takim przypadku uważam, że meld <(find dir1 -ls ) <(find dir2 -ls)działa całkiem dobrze, stosując podstawianie procesu bash. (zsh =(command)działa jeszcze lepiej.)
Popup
10

Kanałowy rodak „billings” (sławy freenode / # centos) podzielił się ze mną swoją metodą:

diff -Naur dir1/ dir2

Dołączenie ukośnika końcowego katalogu końcowego nie ma znaczenia.

Wygląda też na to, że -uopcja nie jest dostępna w niektórych starszych / serwerowych wersjach diff.

Różnica w różnicach:

# 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
todd_dsm
źródło
2
To właśnie --new-file/-Nsprawia, że ​​diff uważa brakujące pliki za puste i --text/-apowoduje, że wszystkie dane binarne są traktowane jako tekst. Nie widzę zalet tego konkretnego przypadku użycia.
phk
4

Diffoscope to świetne narzędzie do porównywania katalogów oparte na linii poleceń.

Szczególnie podoba mi się to, że może różnić się w pliki:

Rekurencyjnie rozpakuje różnego rodzaju archiwa i przekształci różne formaty binarne w bardziej czytelne dla ludzi, aby je porównać. Może równie łatwo porównywać dwa pliki tar, obrazy ISO lub pliki PDF.

Nie tylko powie Ci, które pliki się różnią, ale także jak się różnią.

nh2
źródło
4

Aby znaleźć diff, użyj tego polecenia:

diff -qr dir1/ dir2/

-r będzie również różnicować wszystkie podkatalogi. -q mówi, aby diff raportował tylko wtedy, gdy pliki się różnią.

diff  --brief dir1/ dir2/

--brief pokaże pliki, które nie istnieją w katalogu.

Albo

możemy użyć Melda, który pokaże w oknie graficznym, jak łatwo znaleźć różnicę.

meld  dir1/ dir2/
Javeed Shakeel
źródło
2
--briefi -qsą tą samą opcją. Twoje stwierdzenie brzmi, jakby były różne, ale nie są.
Elijah Lynn
2

Możesz także użyć Rsynci find. Dla find:

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

Ale pliki o tych samych nazwach i w tych samych podfolderach, ale o innej zawartości, nie będą wyświetlane na listach.

Jeżeli jesteś fanem GUI, można sprawdzić Meld że @Alexander wspomniałem. Działa dobrze zarówno w systemie Windows, jak i Linux.

Fábio
źródło
1

Aby zgłosić różnice między dirA i dirB, jednocześnie aktualizując / synchronizując.

rsync -auv <dirA> <dirB>

Kickaha
źródło