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

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

diff -r dir1/ dir2/

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

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


person Mansoor Siddiqui    schedule 14.02.2011    source источник
comment
Дубликат Как сравнить различия между каталогами (linux)   -  person Dan Dascalescu    schedule 06.05.2014
comment
Что касается одного из каталогов, как получить только те файлы / каталоги, которые являются дополнительными в другом?   -  person Sandeepan Nath    schedule 14.04.2016
comment
используйте команду dircmp в unix (не linux)   -  person roblogic    schedule 02.03.2018


Ответы (10)


Пытаться:

diff --brief --recursive dir1/ dir2/

Или, как вариант, с короткими флагами -qr:

diff -qr dir1/ dir2/

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

diff --brief --recursive --new-file dir1/ dir2/  # with long options
diff -qrN dir1/ dir2/                            # with short flag aliases
person Mark Loeser    schedule 14.02.2011
comment
Отлично. Но короче diff -qr dir1/ dir2/, а моя расширенная версия - diff -qr dir1/ dir2/ | grep ' differ' - person sobi3ch; 07.08.2015
comment
@ sobi3ch ваша версия не сообщает о файлах только в одном каталоге - person skv; 30.11.2015
comment
@skv почему? Это та же команда, что и ответ. Я изменил только --brief на ярлык -q. - person sobi3ch; 01.12.2015
comment
@ sobi3ch Я не эксперт :) Я только что запустил его, и он только сказал мне разницу в файлах, а не в файлах, находящихся только в одном месте - person skv; 01.12.2015
comment
@skv Не совсем то, что задан в исходном вопросе, но обновленный ответ, чтобы учесть этот вопрос. - person Mark Loeser; 09.12.2015
comment
Когда я запускаю это (-brief -r), я получаю diff: conflicting output style options diff: Try 'diff --help' for more information. Метод -qr (в ответе ниже) работает нормально. - person Mike Maxwell; 23.10.2018
comment
@MikeMaxwell Это должно быть --brief. -brief интерпретируется как -b -r -i -e -f, другими словами, как набор флагов, а не как одна опция. - person daboross; 25.10.2018
comment
@daboross: вау, я давно использую Unix / Linux и никогда не осознавал, что существует различие между '-' и '-'. (Я не думаю, что "-" существовало, когда я начинал.) Спасибо за объяснение! - person Mike Maxwell; 30.10.2018
comment
@MikeMaxwell Хорошая новость в том, что это просто соглашение. Программы могут интерпретировать их как угодно. Плохая новость в том, что это очень распространенное соглашение почти среди всех инструментов Unix. знак равно - person River Tam; 07.11.2018
comment
- параметры называются параметрами UNIX, а параметры -- называются длинными параметрами GNU в соответствии с man ps. You should make every program accept long options if it uses any options, for this takes little extra work and helps beginners remember how to use the program. источник: gnu.org/software/libc/manual /html_node/Getopt-Long-Options.html, а также google. ru / search? q = gnu + long + options - person Elijah Lynn; 22.02.2019
comment
При необходимости используйте -x или -X, чтобы исключить определенные файлы с помощью шаблонов оболочки. - person ebk; 01.07.2020
comment
@ElijahLynn, специфичный для ps - Unix ps имеет только короткие параметры, в то время как версия GNU дополнительно предоставляет длинные параметры. В общем, они просто называются короткими опционами и длинными опционами. Хотя это всего лишь соглашение - например, find использует - для длинных опций. - person Leonardo Dagnino; 23.02.2021

Я использую следующую команду:

diff -qr dir1/ dir2/

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

diff  --brief --recursive dir1/ dir2/

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

person FPC    schedule 01.09.2012
comment
цените последовательность - но не расстраивайтесь; Я тоже поддержал ответ Марка;) - person Gerard ONeill; 09.03.2015
comment
.. так имеет ли смысл ставить разные ответы ТОЛЬКО с разным оттенком? ИМХО нет! Имеет ли смысл объединить оба ответа в один последовательный ответ? да! ;) - person sobi3ch; 07.08.2015
comment
Просто вопрос; что означает q? Это аббревиатура чего-то? Я не могу найти никакой логики в q .. - person kramer65; 06.11.2016
comment
@ kramer65 - это то же самое, что и --brief, но я думаю, вам интересно, почему q? Может, на короткое время? -b берется путем игнорирования изменений количества пробелов в соответствии со страницей руководства. - person FPC; 23.11.2016
comment
@ sobi3ch Вы правы, еще раз прошу прощения. В свою защиту, я не думаю, что в то время у меня была возможность редактировать другой ответ. - person FPC; 23.11.2016
comment
@ kramer65 Я считаю, что q означает quiet, что обычно означает менее подробный. - person Gogeta70; 15.08.2017
comment
Комментарии здесь демонстрируют, почему мы также должны использовать длинные параметры в наших примерах. Длинные варианты в основном самодокументируются. Когда кто-то использует короткие параметры, они объясняют, что он делает вне кода, но почему бы просто не поместить это в код в качестве более удобочитаемого примера в первую очередь? На странице GNU Long Options даже указано You should make every program accept long options if it uses any options, for this takes little extra work and helps beginners remember how to use the program. source: gnu .org / software / libc / manual / html_node / Getopt-Long-Options.html. - person Elijah Lynn; 22.02.2019
comment
Рассмотрите возможность добавления --no-dereference. - person Tom Hale; 02.08.2019

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

person Alan Porter    schedule 16.03.2014
comment
Аккуратный. Кто бы мог подумать, что git может различать произвольные каталоги, а не только репозиторий со своими файлами? - person Dan Dascalescu; 06.05.2014
comment
Здесь очень полезен сценарий Perl colordiff, его можно использовать с svn и обычным diff. - person Felipe Alvarez; 15.05.2014
comment
Если вы сравниваете (как я) 2 каталога как отдельные проекты / репозитории git, вам нужно добавить --no-index больше на stackoverflow.com/a/1792477/ 473390. Я обновил ответ @ alan-porter. - person sobi3ch; 07.08.2015
comment
Мне нравится этот, я также обнаружил, что если вы добавите --name-status в командную строку, он просто покажет список имен файлов с флагами M / A / D для статуса Modified / Added / Deleted. - person gzh; 27.02.2020
comment
Бывает, что оба каталога фактически содержат папку .git, как я могу исключить ее из сравнения? - person Silidrone; 28.03.2020

Использование rsync:

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

В качестве альтернативы, используя diff:

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

Они функционально эквивалентны, но производительность может варьироваться в зависимости от:

  • Если каталоги находятся на одном диске, rsync работает быстрее.
  • Если каталоги находятся на двух разных дисках, diff выполняется быстрее.

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

person CodeBug    schedule 06.12.2016
comment
rsync не только быстрее для файлов на отдельных дисках, но также позволяет сравнивать файлы в подкаталогах, например rsync --options /usr /bin /var /sbin /lib /old_root будет эффективно сравнивать текущий корневой каталог / (указав в нем все подкаталоги) и /old_root (содержащий, например, некоторую старую резервную копию /), чего diff -r сделать не может. И если вы предполагаете, что файлы с одинаковым размером, разрешениями и отметками времени, вероятно, не изменились, исключение --checksum предоставит вам чрезвычайно быструю (если не полную) проверку того, какие файлы могли быть изменены. - person Matija Nalis; 20.08.2017
comment
Какова цель --delete с rsync? - person Tom Hale; 07.09.2017
comment
Цель --delete - удалить существующие файлы в каталоге назначения, которые (больше не) присутствуют в исходном каталоге. - person Thomas Munk; 08.09.2017
comment
В этом случае (с флагом --dry-run) на самом деле ничего не удаляется, rsync выводит только файлы, которые находятся в каталоге dir1, но не в каталоге dir2. - person mata; 02.10.2017
comment
Я бы рекомендовал всегда ставить --dry-run на первое место, чтобы случайно не забыть об этом. - person Dave Rager; 12.04.2018
comment
Оба (diff и rsync) на самом деле дают несколько разные результаты. Рассмотрим два дерева каталогов, в которых отсутствует testing123 / A / f1, отсутствует testing456 / A / B / f4, а файлы / A / B / C / f9 разные. diff ‹flags› testing123 / testing456 / дает 3 строки, в которых указано, что f9, f4 и f1 различаются. rsync ‹flags› testing123 / testing456 / производит: удаление A / f1 A / B / f4 A / B / C / f9 По крайней мере, я знаю, что слева отсутствует f1, но мне все еще нужно понять, почему f4 и f9 различаются. - person DeanM; 08.12.2018
comment
Решение rsync очень полезно, если вам нужно сравнить локальный каталог с удаленным, доступным через ssh. - person Francesco Frassinelli; 22.05.2019
comment
--no-ignore-file-name-case не требуется: параметр --no-ignore-file-name-case отменяет действие параметра --ignore-file-name-case, возвращаясь к поведению по умолчанию. ': From здесь - person Tom Hale; 02.08.2019

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

meld dir1/ dir2/

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

person Alexander    schedule 09.02.2017
comment
Отлично. Я написал простой скрипт на Perl для сравнения деревьев, но у меня есть ограничения. Кажется, это билет. - person David Tonhofer; 19.05.2017
comment
Единственная проблема в том, что оно не поддается написанию сценариев, поскольку это графическое приложение. Но хорошо, если вы не против графического интерфейса! Спасибо. - person DeanM; 08.12.2018
comment
Я обнаружил, что meld становится ужасно вялым, если его использовать в больших каталогах. Есть ли что-нибудь, что лучше справляется с большими каталогами? - person Popup; 06.09.2019
comment
@Popup, насколько мне известно. Однако вы можете найти разные имена файлов примерно так: find dir1 dir2 | cut -d/ -f2- | sort | uniq --unique - person Alexander; 06.09.2019
comment
@Alexander - В этом случае я обнаружил, что meld <(find dir1 -ls ) <(find dir2 -ls) работает очень хорошо, используя замену процесса bash. (=(command) zsh работает даже лучше.) - person Popup; 10.09.2019

Соотечественник канала billings (из 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
person todd_dsm    schedule 18.09.2015
comment
Таким образом, --new-file/-N заставляет diff рассматривать отсутствующие файлы как пустые и --text/-a, что заставляет его рассматривать весь двоичный ввод как текст. Я не вижу плюсов для этого конкретного варианта использования. - person phk; 08.10.2016

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

diff -qr dir1/ dir2/

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

diff  --brief dir1/ dir2/

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

Или еще

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

meld  dir1/ dir2/
person Javeed Shakeel    schedule 15.03.2018
comment
--brief и -q - это один и тот же вариант. В вашем заявлении звучит так, будто они разные, но это не так. - person Elijah Lynn; 22.02.2019

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

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

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

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

person nh2    schedule 14.06.2017

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

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

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

Если вам нравится графический интерфейс, вы можете проверить Meld, что @ Александр. Он отлично работает как в Windows, так и в Linux.

person Fábio    schedule 27.11.2017

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

rsync -auv <dirA> <dirB>
person Kickaha    schedule 21.02.2020
comment
Хотя это может сработать, использование rsync добавляет уровень сложности, потому что теперь вам нужна эта зависимость. Это хороший залог, но, на мой взгляд, он использует немного больше, чем просто Linux. - person Lomefin; 27.12.2020
comment
@Lomefin Я не понимаю, насколько rsync меньше Linux, чем diff. @Kickaha Вам определенно нужна резервная копия вашего целевого каталога перед запуском этой команды. - person Mogens TrasherDK; 28.12.2020