diff рекурсивно каталог, ігноруючи всі двійкові файли


77

Робота над коробкою Fedora Constantine. Я переглядаю diffдва каталоги рекурсивно, щоб перевірити наявність змін у джерелі. Завдяки налаштуванню проекту (до мого власного залучення до цього проекту! Зітхання ), каталоги містять як джерело, так і двійкові файли, а також великі набори двійкових даних. Хоча різниця врешті-решт працює в цих каталогах, може знадобитися двадцять секунд, якби я міг ігнорувати двійкові файли.

Наскільки я розумію, diff не має режиму `` ігнорувати двійковий файл '', але має аргумент ігнорувати, який ігноруватиме регулярний вираз у файлі. Я не знаю, що там писати, щоб ігнорувати двійкові файли, незалежно від розширення.

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

diff -rq dir1 dir2

2
Спробуйте використовувати cmpзамість diff, не ігноруватимуть двійкові файли, але це має бути швидше
Фредрік Піл

2
іек. це плакат-дочірнє обґрунтування контролю джерела. якщо ти ним не користуєшся, повинен бути. якщо рішення не у ваших руках, вам слід пристрасно сперечатися. Ваша проблема зникне при правильному налаштуванні git ...
fearlesstost

6
О повір мені. Я знаю. Я займаюся переддипломним дослідженням, і це не зовсім так, як слід. Повір мені. Я ЗНАЮ. CVS / SVN / GIT це виправило б. Знаєте, що гірше за це? Мене доручили працювати над проектом Fortran, де документація майже не знайдена. У цьому каталозі є 8 версій проекту, і кожна з них має різні файли make-файлів, які (майже;)) роблять те саме. Повірте мені, я якомога сперечаюся зі своїм наглядачем.
Zéychin

Відповіді:


32

Можливо, використовувати grep -I(що еквівалентно grep --binary-files=without-match) як фільтр для сортування двійкових файлів.

dir1='folder-1'
dir2='folder-2'
IFS=$'\n'
for file in $(grep -Ilsr -m 1 '.' "$dir1"); do
   diff -q "$file" "${file/${dir1}/${dir2}}"
done

Це виглядає надзвичайно багатообіцяючим. Я перевірю це і повідомлю вам, як це відбувається / приймі як відповідь, якщо це вдасться!
Zéychin

2
Хтось знає мету IFS=$'\n'?
Зубін

5
Це внутрішня змінна bash. Шукайте IFS у розділі tldp.org/LDP/abs/html/internalvariables.html для його точного визначення та поведінки.
Harsh J

1
@Zubin IFS означає внутрішній роздільник поля, який використовується для створення масиву шляхом розбиття рядка за значенням, заданим IFS
Be Wake Pandey


65

Вид обману, але ось що я використав:

diff -r dir1/ dir2/ | sed '/Binary\ files\ /d' >outputfile

Це рекурсивно порівнює dir1 з dir2, sed видаляє рядки для двійкових файлів (починається з "Двійкові файли"), а потім перенаправляється у вихідний файл.


7
@Serg Ви можете виключити файли, використовуючи -xпрапор. Спробуйте diff -r -x '*.xml' dir1 dir2також, man diffщоб отримати додаткову інформацію.
xdhmoore

1
Якщо ви використовуєте систему з іншою мовою, замініть Binary\ files\ відповідним словом вашої мови. Це має бути перше одне-два слова. Німецькою мовоюBinärdateien\
кап

1
@xdhmoore Дякую за коментар! Додавання до нього -xтакож є повторюваним, бо якщо ви хочете виключити кілька шаблонів. Щось на зразок -x '*.ext1' -x '*.ext2' -x 'ext3'.
Васан

13

Я прийшов до цього (старого) запитання, шукаючи щось подібне (файли конфігурації на застарілому виробничому сервері порівняно з установкою apache за замовчуванням). Дотримуючись пропозиції @ fearlesstost у коментарях, gitє досить легким та швидким, що, мабуть, є більш простим, ніж будь-яка з наведених вище пропозицій. Скопіюйте версію1 у новий каталог. Тоді зробіть:

git init
git add .
git commit -m 'Version 1'

Тепер видаліть усі файли з версії 1 у цьому каталозі та скопіюйте версію 2 у каталог. Тепер зробіть:

git add .
git commit -m 'Version 2'
git show

Це покаже вам версію Git про всі відмінності між першим комітом і другим. Для двійкових файлів це просто скаже, що вони відрізняються. Крім того, ви можете створити гілку для кожної версії та спробувати об’єднати їх за допомогою інструментів злиття git.


5

Якщо імена довічних файлів в проекті по наступною схемою конкретної ( *.o, *.so, ...) , як вони зазвичай роблять, ви можете помістити ці шаблони в файл і вказати його з допомогою-X (дефіс X).

Зміст мого exclude_file

*.o
*.so
*.git

Команда:

diff -X exclude_file -r . other_tree > my_diff_file

ОНОВЛЕННЯ:

-xможе використовуватися замість -X, щоб вказати шаблони виключення в командному рядку, а не у файлі:

diff -r -x *.o -x *.so -x *.git dir1 dir2

1
Це -x НЕ -X.
code_dweller

2
@code_dweller Обидва існують: -xпризначений для виключення шаблону з командного рядка, тоді як -Xвказує файл, що містить усі шаблони, які слід виключити.
simlev

0

Використовуйте комбінацію findта fileкоманди. Для цього потрібно провести певне дослідження результатів роботи fileкоманди у своєму каталозі; внизу я припускаю, що файли, які ви хочете розрізнити, повідомляються як ascii. АБО, використовуйте grep -vдля фільтрації двійкових файлів.

#!/bin/bash

dir1=/path/to/first/folder
dir2=/path/to/second/folder

cd $dir1
files=$(find . -type f -print | xargs file | grep ASCII | cut -d: -f1)

for i in $files;
do
    echo diffing $i ---- $dir2/$i
    diff -q $i $dir2/$i
done

Оскільки ви, мабуть, знаєте імена величезних двійкових файлів, розмістіть їх у хеш-масиві і виконуйте різницю лише тоді, коли файлу немає в хеші, приблизно так:

#!/bin/bash

dir1=/path/to/first/directory
dir2=/path/to/second/directory

content_dir1=$(mktemp)
content_dir2=$(mktemp)

$(cd $dir1 && find . -type f -print > $content_dir1)
$(cd $dir2 && find . -type f -print > $content_dir2)

echo Files that only exist in one of the paths
echo -----------------------------------------
diff $content_dir1 $content_dir2    

#Files 2 Ignore
declare -A F2I
F2I=( [sqlite3]=1 [binfile2]=1 )

while read f;
do
    b=$(basename $f)
    if ! [[ ${F2I[$b]} ]]; then
        diff $dir1/$f $dir2/$f
    fi
done < $content_dir1

0

Ну, як грубу перевірку, ви можете ігнорувати файли, що відповідають / \ 0 /.


1
Проблема в тому, що схоже, що diff навіть взагалі не підтримує ігнорування файлів.
Zéychin

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