Подтвердить что ты не робот

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

Работа над коробкой Fedora Constantine. Я ищу diff две директории рекурсивно, чтобы проверить изменения источника. Из-за настройки проекта (до моего участия в проекте! Sigh) каталоги содержат как исходные тексты, так и двоичные файлы, а также большие наборы двоичных данных. В то время как diffing в конечном итоге работает с этими каталогами, мне потребовалось бы около двадцати секунд, если бы я мог игнорировать двоичные файлы.

Насколько я понимаю, diff не имеет режима "игнорировать двоичный файл", но имеет аргумент игнорирования, который будет игнорировать регулярное выражение внутри файла. Я не знаю, что там писать, чтобы игнорировать двоичные файлы, независимо от расширения.

Я использую следующую команду, но она не игнорирует двоичные файлы. Кто-нибудь знает, как изменить эту команду, чтобы сделать это?

diff -rq dir1 dir2
4b9b3361

Ответ 1

Возможно, используйте 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

Ответ 2

Вид обмана, но вот что я использовал:

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

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

Ответ 3

Я пришел к этому (старому) вопросу в поисках чего-то подобного (файлы Config на устаревшем производственном сервере по сравнению с установкой apache по умолчанию). Следуя предложению @fearlesstost в комментариях, git достаточно легкий и быстрый, что, вероятно, более прямолинейно, чем любое из приведенных выше предложений. Скопировать version1 в новый каталог. Затем выполните:

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

Теперь удалите все файлы из версии 1 в этом каталоге и скопируйте версию 2 в каталог. Теперь выполните:

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

Это покажет вам версию Git всех различий между первым фиксатором и вторым. Для двоичных файлов он просто скажет, что они отличаются. Кроме того, вы можете создать ветвь для каждой версии и попытаться объединить их с помощью инструментов Git merge.

Ответ 4

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

Содержимое моего exclude_file

*.o
*.so
*.git

Команда:

diff -X exclude_file -r . other_tree > my_diff_file

UPDATE:

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

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

Ответ 5

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

Ответ 6

Используйте комбинацию 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

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

#!/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