відрізняється від виводу лише імен файлів


244

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

Відповіді:


376

Зі сторінки чоловіка 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

Спасибі - diffсторінка man у CentOS 7 описує -qяк "звітувати лише тоді, коли файли відрізняються", що менш зрозуміло, ніж те, що ви написали.
Ч.

2
Це порівнює фактичний вміст файлів, який часто потрібен, однак відповідь rsync дає можливість дивитися лише назви та розміри файлів, а не вміст; що іноді бажано.
steveb

Працює і на macOS.
Маріус Сутьє

Крім того, може включати -x PATTERNв команду для виключення певних підкаталогів. Наприклад, diff -qr repo1 repo2 -x ".git" порівняємо два каталоги, але виключатиме шляхи до файлів з ".git" в них.
ViFI

27

Ви також можете використовувати rsync

rsync -rv --size-only --dry-run /my/source/ /my/dest/ > diff.out

6
--size-onlyбуде пропускати файли однакового розміру, але різного вмісту, наприклад, старий / версія.txt "29a" new / version.txt "29b" . Використовуйте натомість: rsync -ric --dry-run old/ new/де аргумент "-i" дозволяє отримати список файлів безпосередньо черезrsync -ric --dry-run old/ new/ | cut -d" " -f 2
iolsmit

6
Це чудово, якщо ви шукаєте лише відсутні файли (особливо для мережевих спільних ресурсів), оскільки він не порівнює вміст. Це допомогло мені знайти кілька файлів, які не вдалося під час переходу до нового NAS.
OverZealous

4
Не забудьте включити прорізну рису для контурів, вказаних у командному рядку rsync. Без них це не працюватиме правильно, і rsync, ймовірно, просто перелічить усі назви файлів!
Володимир Пантелеев

2
Що стосується коментарів щодо неперевірки вмісту. Іноді це бажано, принаймні як перший прохід.
steveb

13

Якщо ви хочете отримати список файлів, які знаходяться лише в одному каталозі, а не їхні підкаталоги та лише їхні назви файлів:

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 {}

9

У моїй системі Linux, щоб отримати лише імена файлів

diff -q /dir1 /dir2|cut -f2 -d' '

7
Я не ставлю назви файлів з пробілами в моїй системі Linux. ;)
gerardw

6
Я не хотів , щоб приписувати це до вас ... ;-p Так само , як натяк на кого - то , хто робить ...
michuelnik

не працює для мене. Структура мого каталогу, як нижче,audit-0.0.234/audit-data-warehouse-0.0.234/ audit-0.0.235/audit-data-warehouse-0.0.235/
Alex Raj Kaliamoorthy

diff -qrN /dir1 /dir2 | cut -f2 -d' 'добре працює для мене!
Франческо

9

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

Для створення списку нових або модифікованих файлів програмно найкращим рішенням, який я міг би придумати, є використання rsync , сортування та 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 -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" "вивести оновлення, використовуючи вказаний FORMAT", який тут "% n" лише для імені файлу

Вихід (список файлів) rsyncобох напрямків поєднується та сортується за допомогою sort, і цей відсортований список згортається, видаляючи всі дублікати зuniq


Ви не можете просто запустити його назад ( diff new/ old/), щоб побачити, які каталоги видалено?
Жак

Запущений diff -qr new/ old/на прикладі вище з dokuwiki tars видає такий же вихід, як diff -qr old/ new/- тобто ви бачите, що каталог новий / відсутній, але не файли в ньому
iolsmit

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.