Як відрізняти кілька файлів у каталогах?


19

Я намагаюся знайти diffs між усіма файлами з однаковими іменами в двох примірниках каталогу (скажімо, робочих та резервних копій). Наприклад, я можу diffдва файли з однаковим іменем в обох:

> diff d1/f.cpp d2/f.cpp

або я можу знайти відмінності в каталогах:

> diff d1 d2

але як я можу знайти відмінності лише між *.cppфайлами?

> diff d1/*.cpp d2/*.cpp

здається, не працює (з очевидних причин).

[Це, мабуть, легко вирішити за допомогою циклів, але я намагаюся знайти більш елегантний спосіб]

Відповіді:


13

Ви можете використовувати цикл оболонки, який виконує diff для кожного файлу, хоча це не сприйме випадки, коли d2 містить файл, але d1 - ні. Це, можливо, буде достатньо.

for file in d1/*.cpp; do
    diff "$file" "d2/${file##*/}"
done

Або все в одному рядку:

for file in d1/*.cpp; do diff "$file" "d2/${file##*/}"; done

${file##*/}Частина являє собою спеціальний параметр розширення.

Якщо змінна файлу містить d1/hello.cpp, то "${file##*/}"вона розшириться до hello.cpp(значення файлу, але з усім, що стосується останнього / видаленого, включаючи останнє / видалене).

Таким чином, "d2/${file##*/}"це призведе до d2/hello.cppі, таким чином, команда diff є таким чиномdiff d1/hello.cpp d2/hello.cpp

Дивіться http://mywiki.wooledge.org/BashFAQ/100 для отримання додаткових відомостей про струнні маніпуляції в bash.

З іншого боку, система контролю версій (наприклад, підривна робота, git, mercurial тощо) дозволила б значно полегшити подібний тип.


Я думаю, що з двох чудових відповідей ця ситуація є більш прямою вперед, коли є кілька типів файлів (хоча я згадував у питанні, що шукаю рішення без циклу), тому я прийняв це. Одне додавання додається echo "${file##*/}";перед diffкомандою, тож відомо, з якими файлами насправді порівнюється. Також, як згадувалося у відповіді @ Rinzwind, цей спосіб не охоплює справи, якщо список файлів не є однаковим в обох каталогах.
ysap

52

diff -qr {DIR1} {DIR2} робить усі файли в обох каталогах.

  • q показує лише відмінності
  • rробить рекурсивним. Залиште це, якщо вам це не потрібно

Ви не можете сказати diffбезпосередньо використовувати символи, але можете додати:

-x PAT  --exclude=PAT
    Exclude files that match PAT.

-X FILE    --exclude-from=FILE
   Exclude files that match any pattern in FILE.

для виключення файлів. Тож якщо ви хочете *.cppлише найпростіший метод - це створити текстовий файл, у якому перераховані всі файли, які не є *.cpp. Це можна зробити за допомогою наступної команди: ls -I "*.cpp" > excluded_filesде -I "*.cpp"аргумент ігнорує всі файли .cpp. Зверніть увагу, що лапки необхідні.


Просто, і працює бездоганно.
Хосе Гомес

4

Через деякий час, поставивши запитання, я виявив meldутиліту diff, і відтоді її використовую. Це чудова частина програми на основі GUI, яка робить порівняння та злиття між файлами та каталогом дуже легким завданням. Це дво- або тристоронні порівняння.

Зокрема, він відповідає на моє оригінальне запитання тим, що показує кольорове порівняння вмісту каталогів і дозволяє порівнювати конкретні файли подвійним клацанням на ім'я файлу.

Якщо вам потрібно більше, ніж тристороннє порівняння, то gvimdiff(на основі vimредактора) теж чудово, що забезпечує цю функціональність.


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