首先,我尝试在askubuntu上问同样的事情,但我没有到达那里...... https://askubuntu.com/questions/186114/how-to-diff-two-folders-to-multiple-patch-files/186121#comment231985_186121
所以,我会复制/粘贴在这里希望SO给我一个有效的解决方案......
我不是一个unix家伙所以我会继续问:
我有以下问题 - 两个包含大量子文件夹的文件夹。我需要区分它们。
我试过了:
diff -drupN vanila_kernel_3.0.8 my_kernel_3.0.8 > kernel.patch
导致185mb文件...而不是我想要的。
我希望diff的结果是许多较小的补丁,理想情况下,每个更改的文件都有一个补丁内容。这意味着我必须改变我使用diff的方式,我需要把它放在某种循环中......所以我试着运行这个小脚本
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上浪费时间。
答案 0 :(得分: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..
会为每个更改的文件运行循环体,文件名存储为f1
和f2。
filename=${f1#$DIR1} # remove base dir name
这会删除文件名的尾部(通过删除基目录),这样我们就可以确定输出补丁文件的正确路径。之后,只需要确保输出目录存在,并在f1
和f2
上写出差异结果。
所有文件名的引号确保我们可以处理文件名中的空格。
答案 1 :(得分:2)
你可以抓住&lt; Learning Perl&gt;预订并在一周内学习,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&gt; patch&amp;&amp; rm patch只会删除空的补丁文件。
答案 2 :(得分: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
如果您的文件名包含空格,则可能会中断。
答案 3 :(得分: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文件夹(对于新项目是唯一的)
答案 4 :(得分:0)
列表项
$ diff -rauB old_dir new_dir > patchfile_name
$ patch --dry-run -p1 -i patchfile_name
$ patch -p1 -i patchfile_name
这会在两个目录之间创建一个补丁。