2

首先,我尝试在 askubuntu 上问同样的问题,但我并没有走得太远...... https://askubuntu.com/questions/186114/how-to-diff-two-folders-to-multiple-patch-files/ 186121#comment231985_186121

所以,我会在这里复制/粘贴,希望能给我一个可行的解决方案......

我不是一个 unix 人,所以我会继续问:

我有以下问题 - 两个包含大量子文件夹的文件夹。我需要区分它们。

我试过这个:

diff -drupN vanila_kernel_3.0.8 my_kernel_3.0.8 > kernel.patch

这会产生一个 185mb 的文件......并不是我真正想要的。

我希望差异的结果是许多较小的补丁,理想情况下,每个已更改的文件都有一个包含更改内容的补丁。这意味着我必须改变我使用差异的方式,我需要把它放在某种循环中......所以我尝试运行这个小脚本

for file in original_308/*.*; do
    diff -dupN "$file" "my_308/${file##*/}" > "$file".patch
done

但它不起作用:/

理想情况下,我希望每次更改都有一个 .patch 文件,但是为原始文件更改的文件提供补丁就可以了(因为我可以过滤新添加的文件并将它们复制过来)

有人可以为我提供一个体面的方法吗?

更新:我知道这些文件夹和 4546 个新添加的文件之间有 231 个更改的文件......我只是对生成这 231 个补丁感兴趣。我什至有一个包含这 231 个文件名的文件,因此也可以在脚本中使用。

我用它来生成更改日志

diff -qdr -x *.o -x *.cmd -x *.d original_308 my_308 | sed "s/^.* and \(.*\) differ/\1/" | sort > changes.txt

并且只打印更改的文件名,后跟“仅在 my_308”文件中...... 231 个文件位于该文件的顶部(前 231 行)

所以让我们说清楚 - 我想要源文件的 .patch 文件。如果补丁可以在补丁//file_name.c.patch 中结束,那就太好了……

如果你给我 PERL 脚本,请告诉我如何最好地使用它们,因为我不明白那些垃圾。请不要让我失望。我需要移植、测试和运行这个东西,我在 unix 命令和无形脚本 ffs 上浪费时间。

4

5 回答 5

2

像这样的东西?

DIR1="vanila_kernel_3.0.8"
DIR2="my_kernel_3.0.8"
OUTDIR="patches"
SUFFIX=".patch"

while IFS="," read f1 f2; do
  filename=${f1#$DIR1}  # remove base dir name
  outfile="${OUTDIR}/${filename}${SUFFIX}"
  mkdir -p $(dirname $outfile)  # make sure output directory exist

  diff -dupN "$f1" "$f2" > "$outfile"
done < <(diff -qdr $DIR1 $DIR2 | awk '/differ$/{print $2","$4}')

快速解释:

diff -qdr $DIR1 $DIR2 | awk '/differ$/{print $2","$4}'

这应该会为您提供一份表格中已更改的文件列表source_file,dest_file。将其传递给while ...read..每个已更改文件的循环体,文件名存储为f1f2。

filename=${f1#$DIR1}  # remove base dir name

这会去除文件名的尾随部分(通过删除基本目录),因此我们可以确定输出补丁文件的正确路径。之后,只需确保输出目录存在并在 和 上写出差异f1结果f2

所有文件名的引号确保我们可以处理文件名中的空格。

于 2012-09-10T16:12:37.603 回答
2

你可以拿下《Learning Perl》这本书,一周就学会了,Perl 很酷,请不要说它是垃圾。这是生成补丁的shell脚本

find ./original_308 -type f | while read file
do
  nfile="./my_308/${file#*original_308/}"
  if [ -f $nfile ]; then
    patchfile="./patch/${file#*original_308/}.patch"
    mkdir -p `dirname $patchfile`
    echo "checking $file $nfile"
    diff -dupN "$file" "$nfile" > "$patchfile" && rm "$patchfile"
  fi
done

diff xxx >patch && rm patch 只会删除空的补丁文件。

于 2012-09-10T16:24:27.667 回答
1

这应该适用于kernel.patch文件,即使您提供的选项diff与上面显示的选项不同:

perl -ne 'if(m{^diff .* (.*/.*) (.*/.*)}) {
              my $f = $1;
              $f =~ s{/}{_}g;
              open $FH, ">", "$f.patch" or die $!;
          } else {
              print {$FH} $_;
          }' kernel.patch

如果您的文件名包含空格,这可能会中断。

于 2012-09-10T15:37:59.610 回答
1

感谢大家的贡献...这是最终结果

#!/bin/bash                               
FOLDER_OLD="original"
FOLDER_NEW="changed"
FOLDER_PATCHES="./fresh_patches"

echo "Generating changelog for $FOLDER_OLD --> $FOLDER_NEW"
diff -qdr ${FOLDER_OLD} ${FOLDER_NEW} | sed "s/^.* and \(.*\) differ/\1/" | sort > newchanges.txt

mkdir -p ${FOLDER_PATCHES}                                                                                                           
for newfile in `find $FOLDER_NEW -type f`
do
sufix=${newfile#${FOLDER_NEW}/}
oldfile="${FOLDER_OLD}/${sufix}"

if [ -f $oldfile ]; then
    patchfile="${FOLDER_PATCHES}/`echo $sufix |sed 's/\//_/g'`.patch"
    if [ "`diff $oldfile $newfile`" != "" ]; then
        echo "Make patch ${patchfile}"
        diff -dupN "$oldfile" "$newfile" > "$patchfile"
    fi
else
patchfile="${FOLDER_PATCHES}/ADDONS/${newfile#$FOLDER_NEW}"
    echo "Copy $newfile --> $patchfile"
    mkdir -p "`dirname ${patchfile}`"
    cp $newfile $patchfile
fi
done

该脚本首先生成更改文件列表和仅对新项目/文件夹唯一的文件;然后它为每个文件生成一个补丁文件并将新添加的文件复制到 ADDONS 文件夹(新项目独有)

于 2012-09-12T16:05:20.767 回答
1
  1. 项目清单

             $ diff -rauB  old_dir   new_dir   >  patchfile_name
    
             $ patch --dry-run -p1 -i patchfile_name
    
    
             $ patch -p1 -i patchfile_name
    

这会在两个目录之间创建一个补丁。

于 2013-02-07T06:36:23.240 回答