Учитывая два дерева каталогов, как я могу узнать, какие файлы отличаются по содержанию?


787

Если я хочу найти различия между двумя деревьями каталогов, я обычно просто выполняю:

diff -r dir1/ dir2/

Это выводит именно то, что различия между соответствующими файлами. Я заинтересован в том, чтобы просто получить список соответствующих файлов, содержание которых отличается. Я предполагал, что это просто вопрос передачи параметра командной строки diff, но я не смог найти ничего на странице руководства.

Какие-либо предложения?



1
Что касается одного из каталогов, как получить только те файлы / каталоги, которые являются дополнительными в другом?
Сандипан Нат

использовать dircmpкоманду в Unix (не Linux)
roblogic

Ответы:


1120

Вы сказали Linux, так что вам повезло (по крайней мере, он должен быть доступен, не уверен, когда он был добавлен):

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

Должен делать то, что вам нужно.

Если вы также хотите увидеть различия для файлов, которые могут не существовать ни в одном каталоге:

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

13
Ницца. Но короче diff -qr dir1/ dir2/и моя расширенная версияdiff -qr dir1/ dir2/ | grep ' differ'
sobi3ch

1
@skv почему? Это та же команда, что и ответ. Я изменил только --briefна ярлык -q.
sobi3ch

2
@skv Не совсем то, что задал исходный вопрос, но обновляет ответ, чтобы учесть и этот вопрос.
Марк Лозер

3
@MikeMaxwell Это должно быть --brief. -briefинтерпретируется как -b -r -i -e -f, другими словами, как набор флагов, а не как одна опция.
Даборосс

2
@daboross: вау, я давно пользуюсь Unix / Linux и никогда не осознавал, что существует разница между '-' и '-'. (Я не думаю, что «-» существовало, когда я начал.) Спасибо за объяснение!
Майк Максвелл

287

Команда, которую я использую:

diff -qr dir1/ dir2/

Это точно так же, как и у Марка :) Но его ответ беспокоил меня, поскольку он использует различные типы флагов, и это заставило меня выглядеть дважды. Используя более подробные флаги Марка, это будет:

diff  --brief --recursive dir1/ dir2/

Я извиняюсь за публикацию, когда другой ответ вполне приемлем. Не могу остановить себя ... работаю над тем, чтобы быть менее педантичным.


3
полностью ценю последовательность - но не чувствую себя плохо; Я тоже проголосовал за ответ Марка;)
Джерард ONeill

10
... так есть ли смысл ставить разные ответы просто с другим вкусом? ИМХО нет! Имеет ли смысл объединять оба ответа в один последовательный ответ? да! ;)
sobi3ch

1
Просто вопрос; что означает qстенд? Это аббревиатура чего-то? Я не могу найти никакой логики за q..
kramer65

3
@ kramer65 - это то же самое, что и "--brief", но я думаю, вы удивляетесь, почему q? Возможно для быстрого? «-b» используется «игнорировать изменения количества пустого пространства» в соответствии с man-страницей.
FPC

4
@ kramer65 Я считаю, что qэто quiet, как правило, означает менее многословно.
Gogeta70

105

Мне нравится использовать git diff --no-index dir1/ dir2/, потому что это может показать различия в цвете (если у вас есть эта опция установлена ​​в вашем git config) и потому что это показывает все различия в длинном постраничном выводе, используя «less».


25
Ухоженная. Кто бы мог подумать, что git может различать произвольные каталоги, а не только репо с его файлами?
Дан Даскалеску

2
Здесь очень полезен Perl-скрипт colordiff , который можно использовать с svn и normal diff.
Фелипе Альварес

4
Если вы сравниваете (как и я) 2 dirs с отдельными git-проектами / репозиториями, вам нужно добавить --no-indexбольше на stackoverflow.com/a/1792477/473390 . Я обновил ответ @ alan-porter.
sobi3ch

Мне нравится этот, я также нахожу, что если вы добавите --name-status в командную строку, он просто покажет список имен файлов с флагами "M / A / D" для статуса Модифицированный / Добавленный / Удаленный.
Гж

Бывает так, что оба каталога на самом деле содержат папку .git, как я могу исключить ее из сравнения?
Мухамед Чикак

35

Эти две команды в основном делают то, что просили:

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

Выбор между ними зависит от расположения dir1 и dir2:

Когда каталоги находятся на двух отдельных дисках, diff превосходит rsync. Но когда две сравниваемые директории находятся на одном диске, rsync работает быстрее. Это связано с тем, что diff создает почти одинаковую нагрузку на обе директории параллельно, максимизируя нагрузку на два диска.

rsync вычисляет контрольные суммы в больших кусках, прежде чем сравнивать их. Это группирует операции ввода-вывода в большие порции и приводит к более эффективной обработке, когда все происходит на одном диске.


3
rsync не только быстрее для файлов на отдельных дисках, но также позволяет сравнивать файлы в подкаталогах, например rsync --options /usr /bin /var /sbin /lib /old_root, эффективно сравнивает текущий корень /(указав в нем все подкаталоги) и /old_root(содержащий, например, некоторую более старую резервную копию /), что diff -rможет не делай И если вы предполагаете, что файлы с одинаковым размером, разрешениями и временными метками, вероятно, не изменились, исключение --checksumпредоставит вам чрезвычайно быструю (если не так сквозную) проверку того, какие файлы могли измениться.
Матия Налис

1
Какова цель --deleteс rsync?
Том Хейл,

2
Цель --delete состоит в том, чтобы удалить существующие файлы в destination-dir, которые больше не присутствуют в source-dir
Томас Мунк,

2
В этом случае (с --dry-runфлагом) ничего действительно не удаляется, rsyncтолько печатает, какие файлы находятся в dir1, но не в dir2
mata

11
Я бы порекомендовал ставить --dry-runпервым всегда, чтобы не случайно забыть об этом.
Дейв Рэйджер

22

Meld также является отличным инструментом для сравнения двух каталогов:

meld dir1/ dir2/

У Meld есть много опций для сравнения файлов или каталогов. Если два файла отличаются, легко войти в режим сравнения файлов и увидеть точные различия.


2
Ницца. Я написал простой Perl-скрипт для сравнения деревьев, но я ограничиваюсь. Это похоже на билет.
Дэвид Тонхофер

Единственная проблема заключается в том, что он не поддается сценариям, поскольку это графическое приложение. Но хорошо, если вы не против графического интерфейса! Спасибо.
ДеканМ

Я считаю, что это meldстановится ужасно вялым, если используется на больших каталогах, хотя. Есть ли что-нибудь, что лучше обрабатывает большие каталоги?
всплывающее окно

@ Попап, не то, что я знаю. Вы можете найти разные имена файлов с чем-то вроде этого, хотя:find dir1 dir2 | cut -d/ -f2- | sort | uniq --unique
Александр

1
@ Александр - В этом случае я нахожу, что это meld <(find dir1 -ls ) <(find dir2 -ls)работает довольно хорошо, используя замену процесса bash. (Zsh =(command)работает даже лучше.)
всплывающее окно

10

Канал соотечественника 'Биллингс' (известности freenode / # centos) поделился со мной своим методом:

diff -Naur dir1/ dir2

Включение прямой косой черты в каталог не имеет значения.

Кроме того, кажется, что -uопция недоступна в некоторых старых / серверных версиях diff.

Разница в различиях:

# 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
Это то, --new-file/-Nчто заставляет diff считать отсутствующие файлы пустыми, а --text/-aвсе двоичные входные данные - текстом. Я не вижу преимуществ для этого конкретного случая использования.
phk

4

Diffoscope - отличный инструмент для работы с каталогами, основанный на командной строке.

Мне особенно нравится, что он может различаться в файлах:

Он будет рекурсивно распаковывать архивы многих типов и преобразовывать различные двоичные форматы в более удобочитаемую форму для сравнения. Он может так же легко сравнивать два архива, ISO-образы или PDF.

Он не только скажет вам, какие файлы отличаются, но и как они отличаются.


4

Чтобы найти diff, используйте эту команду:

diff -qr dir1/ dir2/

-r будет также различать все подкаталоги -q заставляет diff сообщать, только когда файлы различаются.

diff  --brief dir1/ dir2/

--brief покажет файлы, которые существуют в каталоге.

Или еще

мы можем использовать Meld, который покажет в графическом окне, что легко найти разницу.

meld  dir1/ dir2/

2
--briefи -qтакой же вариант. Ваше заявление звучит так, будто они разные, но это не так.
Элайджа Линн

2

Вы также можете использовать Rsyncи find. Для find:

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

Но файлы с одинаковыми именами и в тех же подпапках, но с разным содержимым не будут отображаться в списках.

Если вы являетесь поклонником GUI, вы можете проверить оплавления , что @Alexander упоминается. Он отлично работает как в Windows, так и в Linux.


1

Чтобы сообщить различия между dirA и dirB, а также обновление / синхронизация.

rsync -auv <dirA> <dirB>

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.