Linux: Порівняйте структуру каталогів без порівняння файлів


55

Який найкращий і найпростіший спосіб порівняти дві структури каталогів, фактично не порівнюючи дані у файлах? Це добре працює:

diff -qr dir1 dir2_

Але це дуже повільно, оскільки він порівнює файли теж. Чи є перемикач для diff чи інший простий інструмент для цього?


Під "структурою каталогів" ви маєте на увазі лише каталоги, або шляхи файлів каталогів і не-каталогів?
інтуїтивно

Так, папки та файли.
Йона

1
У такому випадку слід вилучити цю -type dопцію з відповіді @ slartibartfast або перевірити мою відповідь.
інтуїтивно

Відповіді:


36

Наступні (якщо ви замінюєте перший каталог для каталогу1, а другий для каталогу2), повинні робити те, що ви шукаєте, і швидко:

find directory1 -type d -printf "%P\n" | sort > file1
find directory2 -type d -printf "%P\n" | sort | diff - file1

Основний принцип полягає в тому, що він виводить усі каталоги, включаючи підкаталоги, відносно базових каталогів N.

Це може падати вниз (виробляти wierd вихід), якщо у вас є повернення каретки в деяких назвах каталогу, але не в інших.


Для мене це не корисно, тому що якщо в одному каталозі міститься папка з кількома тисячами файлів, вони перераховані окремо, тоді як diff -rqпросто показує, що кореневий каталог існує в одному і продовжується.
Кріс Джефферсон

Як інтуїтивно вказувало (роки тому), щоб відповісти на питання ОП, -типу d слід видалити, щоб файли враховувались у порівнянні, а також каталоги
user2746401

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

34
vimdiff <(cd dir1; find . | sort) <(cd dir2; find . | sort)

дасть вам приємне відображення двох ієрархій каталогів зі складеними загальними розділами.


Це рішення виходить випадковим чином. Коли vim читає (або перечитує) тимчасовий дескриптор файлу, він уже зник.
Denilson Sá Maia

23

Я зазвичай використовую rsyncдля цього завдання:

rsync -nav --delete DIR1/ DIR2

Будьте ДУЖЕ Дбайливими завжди використовувати параметр-n, aka--dry-run, або він синхронізує (змінить вміст) каталогів.

Це дозволить порівняти файли на основі часу та розмірів модифікації файлів ... Я думаю, що саме цього ви хочете, або, принаймні, ви не заперечуєте, якщо це робиться? Я зрозумів, що ви просто хочете, щоб це сталося швидше , а не те, що вам потрібно, щоб ігнорувати різницю між вмістом файлу. Якщо ви хочете, щоб він не перераховував різні файли з однаковими іменами, я думаю, що додавання --ignore-existingпараметра зробить це.

Також слід пам'ятати , що без введення /в кінці DIR1змусить його порівняти каталог DIR1 з вмістом в DIR2.

Вихід у кінцевому підсумку є трохи дослідним, але він покаже, які файли / каталоги відрізняються. Файли / каталоги, присутні в, DIR2а не в, DIR1будуть мати слово deleting.

У деяких ситуаціях відповідь @ slartibartfast може бути більш підходящою, хоча вам потрібно буде зняти -type dопцію, щоб увімкнути список файлів, що не містять каталогів. rsyncбуде швидше, якщо у вас буде значна кількість файлів / каталогів для порівняння.


Відмінна відповідь. У вихідних даних rsync важко помітити deleting...текст, але це, мабуть, один з кращих способів порівняння файлів, зберігаючи швидкість. Інші відповіді тут швидше, коли не потрібні різні файли ... як у прикладі ОП, але мені це дуже подобається.
Джоел Меллон

Це те, що я був після. У масивної пари дерев каталогів у мене було декілька файлів різного розміру, і я хотів знати, які з них. Це досягнуто цієї мети за лічені секунди.
suprjami

Можливо, це гарна ідея запустити його з користувачем, який має доступ лише для читання. Як і за sudo -u nobody rsync -nav --delete d1 d2умови, що прапори для "інших" дозволяють читати.
користувач1182474

Під час виконання цього рішення я отримав "список файлів побудови ... виконано \ n відправлено X байт отриманих Y байтів Z байт / сек. Загальний розмір - прискорення B" (де я замінив XYZAB на номери). Чи означає це, що все було ідентично? Оскільки вона не згадувала нічого більш конкретного? Заздалегідь дякую
Скотт Н

Щоб відповісти на власне запитання, я експериментував, додаючи різні файли до кожного, і, здається, що жодні конкретні файли / файли, згадані у висновку, означають, що вони всі однакові.
Скотт Н

18

Схожий на відповідь ls, але якщо ви встановите дерево, то можете

tree dir1 > out1
tree dir2 > out2
diff out1 out2

7
Або щоб уникнути tmpfiles,diff <( tree dir1 ) <( tree dir2 )
Джоел Меллон

1
Я рекомендую запустити дерево з iпрапором, який не друкує рядки дерева ( tree -i dir1тощо). Якщо структура каталогів відрізняється в одному місці, інші файли, які відповідають, можуть мати більше або менше |символів у дереві виводу, і diff буде вловлювати ці рядки, навіть якщо шляхи до файлів однакові.
askewchan

2
diff <(дерево -i dir1) <(дерево -i dir2) - це безумовно найкраща відповідь. Я спокушаюсь оскаржити всі відповіді, які пропонують різницю або rsync, оскільки запитання прямо говорить НЕ для читання вмісту файлу. ПРИМІТКА. Пропозиція щодо використання двох труб вимагає ретельного використання проміжків між кронштейнами, точно слідуйте прикладу. Наприклад, для порівняння двох томів 20G після резервного копіювання відповіді дерева було потрібно близько 5 секунд. Інші зайняли 20+ хвилин.
Джейсон Морган

3

Я просто шукав рішення для цієї проблеми. Рішення, яке мені найбільше сподобалось:

comm <(ls DIR1) <(ls DIR2)

Він дає 3 колонки: 1 - файли лише у DIR1, 2 - файли лише у DIR2, 3 - файли лише у DIR3. Детальніше дивіться у цій публікації блогу.


Де DIR3вказано? Все, що я бачу - це DIR1і є DIR2.
Майкл Дорст

Я спробував це, і (від того, що я можу сказати) вихід був: всі файли тільки DIR1в стовпці 1 , всі файли тільки в DIR2в колонці 2 , і всі файли , що розділяються і в колонці 3 . Це щось корисне, але чи знаєте ви, як можна виділити колонку 3 і залишити лише відмінності? У мене дуже багато файлів для сортування, і більшість з них ідентичні. Мені не потрібно бачити, що таке саме.
Майкл Дорст

1
Також я виявив, що comm <(ls DIR1) <(ls DIR2)не працює рекурсивно. Для цього я використав comm <(ls -R1 DIR1) <(ls -R1 DIR2). ls -Rсканується через каталоги рекурсивно, і ls -1(зауважте, що це один , а не L ) робить lsдрукувати лише одне ім'я файлу на рядок.
Майкл Дорст

@Michael: comm -3(див. man comm).
Заз

2
ls > dir1.txt

ls > dir2.txt

Тоді просто розрізняйте два списки.


Складається враження, що ОП хоче герархію шляхів. Це відрізнятиме всі файли в поточному каталозі. Дискусійно, але можливо, що він просто хоче довідники; він може хотіти назви файлів, а не вмісту файлів.
інтуїтивно

@intuited - ти маєш рацію. Я неправильно його прочитав.
MDMarra

2

Це оптимальне рішення

diff --brief -r dir1 dir2

- короткий перемикач повідомляє лише про те, чи відрізняються файли, а не про деталі різниці.


1
В ОП вже є -qпитання, що є псевдонімом для --brief. Ця відповідь не дає жодної нової інформації.
Майкл Дорст

1
OP не хоче порівняння вмісту файлів. But it's really slow because it's comparing files too.
Джоел Меллон

1

використовуйте "diff -qr", щоб отримати різні файли, а потім відфільтруйте порівняння файлів з grep, щоб отримати лише назви файлів, які є лише в одному з каталогів.

diff -qr dir1 dir2 | grep -v "Files.*differ" 

1

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

diff <( cd dir1; find * |sort ) <(cd dir2; find * | sort)

-3

Я думаю, що лише rsync є корисним. чому?

diff корисний лише для структур, що зберігають файли та каталоги. Під час використання символьних посилань Diff не дає адекватних кодів виходу. У цій ситуації diff може повернути 2 вихідних коду, навіть якщо src та dst однакові (час, розміри, імена, часові позначки, вказівні програмні посилання тощо).

dir, файлова система не гарантує впорядкування файлів, навіть якщо вміст каталогів у src та dst однаковий. Можливо, вам слід відфільтрувати вихідний сигнал, сортуючи його. Але чистий ls відображає лише імена вузлів.

можливо, сценарій, що включає diff, cmp, тест -X для типів вузлів буде корисним, але пам’ятайте про перевантаження, зроблене багатьма пробіжками тестів / cmp. Сценарій буде дуже повільним.

Як завжди, якщо ви хочете отримати просту інформацію "dirs is / is unknown", вам слід використовувати rsync з опцією -n (dry). Якщо ви хочете знайти те, що відрізняється, використовуйте команду diff.


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