diff для вывода только имен файлов - PullRequest
213 голосов
/ 02 июня 2011

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

Ответы [ 6 ]

325 голосов
/ 02 июня 2011

со страницы руководства diff:

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

Пример команды:

diff -qr dir1 dir2

Пример вывода (зависит от локали):

$ ls dir1 dir2
dir1:
same-file  different  only-1

dir2:
same-file  different  only-2
$ diff -qr dir1 dir2
Files dir1/different and dir2/different differ
Only in dir1: only-1
Only in dir2: only-2
20 голосов
/ 09 мая 2014

Вы также можете использовать rsync

rsync -rv --size-only --dry-run /my/source/ /my/dest/ > diff.out
12 голосов
/ 31 октября 2013

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

diff -q /dir1 /dir2 | grep /dir1 | grep -E "^Only in*" | sed -n 's/[^:]*: //p'

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

diff -rq /dir1 /dir2 | grep -E "^Only in /dir1*" | sed -n 's/://p' | awk '{print $3"/"$4}'

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

Например, я мог бы удалить все файлы и каталоги, которые находятся в dir1, но не в dir2:

diff -rq /dir1 /dir2 | grep -E "^Only in /dir1*" | sed -n 's/://p' | awk '{print $3"/"$4}' xargs -I {} rm -r {}
8 голосов
/ 25 марта 2015

Подход запуска diff -qr old/ new/ имеет один существенный недостаток: он может пропустить файлы во вновь созданных каталогах. Например. в приведенном ниже примере файл data/pages/playground/playground.txt отсутствует в выводе diff -qr old/ new/, тогда как каталог data/pages/playground/ есть (найдите в браузере plays.txt , чтобы быстро сравнить). Я также разместил следующее решение в Unix & Linux Stack Exchange , но также скопирую его здесь:

Для программного создания списка новых или измененных файлов лучшее решение, которое я мог бы найти, - это использовать rsync , sort и uniq :

(rsync -rcn --out-format="%n" old/ new/ && rsync -rcn --out-format="%n" new/ old/) | sort | uniq

Позвольте мне объяснить на этом примере: мы хотим сравнить два выпуска dokuwiki, чтобы увидеть, какие файлы были изменены, а какие были созданы недавно.

Мы извлекаем файлы с помощью wget и извлекаем их в каталоги old/ и new/:

wget http://download.dokuwiki.org/src/dokuwiki/dokuwiki-2014-09-29d.tgz
wget http://download.dokuwiki.org/src/dokuwiki/dokuwiki-2014-09-29.tgz
mkdir old && tar xzf dokuwiki-2014-09-29.tgz -C old --strip-components=1
mkdir new && tar xzf dokuwiki-2014-09-29d.tgz -C new --strip-components=1

Запуск rsync в одну сторону может пропустить вновь созданные файлы, поскольку сравнение rsync и diff показывает здесь:

rsync -rcn --out-format="%n" old/ new/

дает следующий вывод:

VERSION
doku.php
conf/mime.conf
inc/auth.php
inc/lang/no/lang.php
lib/plugins/acl/remote.php
lib/plugins/authplain/auth.php
lib/plugins/usermanager/admin.php

Запуск rsync только в одном направлении пропускает вновь созданные файлы, а наоборот пропустит удаленные файлы, сравните вывод diff:

diff -qr old/ new/

дает следующий вывод:

Files old/VERSION and new/VERSION differ
Files old/conf/mime.conf and new/conf/mime.conf differ
Only in new/data/pages: playground
Files old/doku.php and new/doku.php differ
Files old/inc/auth.php and new/inc/auth.php differ
Files old/inc/lang/no/lang.php and new/inc/lang/no/lang.php differ
Files old/lib/plugins/acl/remote.php and new/lib/plugins/acl/remote.php differ
Files old/lib/plugins/authplain/auth.php and new/lib/plugins/authplain/auth.php differ
Files old/lib/plugins/usermanager/admin.php and new/lib/plugins/usermanager/admin.php differ

Запуск rsync в обоих направлениях и сортировка выходных данных для удаления дубликатов показывает, что каталог data/pages/playground/ и файл data/pages/playground/playground.txt были изначально пропущены:

(rsync -rcn --out-format="%n" old/ new/ && rsync -rcn --out-format="%n" new/ old/) | sort | uniq

дает следующий вывод:

VERSION
conf/mime.conf
data/pages/playground/
data/pages/playground/playground.txt
doku.php
inc/auth.php
inc/lang/no/lang.php
lib/plugins/acl/remote.php
lib/plugins/authplain/auth.php
lib/plugins/usermanager/admin.php

rsync запускается с этими аргументами:

  • -r "зайти в каталоги",
  • -c для сравнения файлов одинакового размера и только «пропустить на основе контрольной суммы, а не времени и размера мода»,
  • -n для «пробного запуска без внесенных изменений» и
  • --out-format="%n" для «вывода обновлений с использованием указанного ФОРМАТА», что здесь «% n» только для имени файла

Вывод (список файлов) rsync в обоих направлениях объединяется и сортируется с использованием sort, и этот отсортированный список затем сокращается путем удаления всех дубликатов с uniq

8 голосов
/ 19 сентября 2013

В моей системе Linux, чтобы получить просто имена файлов

diff -q /dir1 /dir2|cut -f2 -d' '
0 голосов
/ 18 декабря 2015
rsync -rvc --delete --size-only --dry-run source dir target dir
...