以递归方式区分目录,忽略所有二进制文件

时间:2011-07-15 17:24:34

标签: bash shell diff binaryfiles

使用Fedora Constantine框。我正在寻找diff递归的两个目录来检查源更改。由于项目的设置(在我自己参与所述项目之前!叹息),目录包含源和二进制文件,以及大型二进制数据集。虽然diffing最终可以在这些目录上运行,但如果我可以忽略二进制文件,则可能需要20秒。

据我所知,diff没有'忽略二进制文件'模式,但确实有一个忽略参数,它会忽略文件中正则表达式 。我不知道在那里写什么来忽略二进制文件,无论扩展名如何。

我正在使用以下命令,但它不会忽略二进制文件。有谁知道如何修改此命令来执行此操作?

diff -rq dir1 dir2

6 个答案:

答案 0 :(得分:64)

有点作弊,但这是我用的:

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

这递归地将dir1与dir2进行比较,sed删除二进制文件的行(以“二进制文件”开头),然后将其重定向到输出文件。

答案 1 :(得分: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

答案 2 :(得分:11)

我来到这个(旧)问题寻找类似的东西(遗留生产服务器上的配置文件与默认的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的合并工具合并它们。

答案 3 :(得分:1)

如果项目中二进制文件的名称遵循特定模式(* .o,* .so,...),就像通常那样,您可以将这些模式放在文件中并使用-X指定它(连字符X)。

我的“排除档案”的内容     *的.o     *。所以     * git的

diff -X exclude_file -r . other_tree > my_diff_file

答案 4 :(得分:0)

好吧,作为粗略的检查,您可以忽略与/ \ 0 /.

匹配的文件

答案 5 :(得分:0)

使用findfile命令的组合。这需要您对目录中file命令的输出进行一些研究;下面我假设您要diff的文件报告为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