Take the 2-minute tour ×
Ask Ubuntu is a question and answer site for Ubuntu users and developers. It's 100% free, no registration required.

I'm not much of a unix guy so I'll just go ahead and ask:

I have a following problem - two folders with plenty of subfolders. I need to diff them.

I tried this:

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

and that results in a 85mb file... and not really what I want.

I want the result of the diff to be many smaller patches, ideally one for every changed file with the contents of the change. That means I have t ochange the way I use diff, and I need to put it in some sort of a loop... So i tried running this little script

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

But it doesn't work :/

Ideally, I want to have a .patch file for every change, but having patches for files that changed in original would do just fine (as I could filter the newly added files and just copy them over)

Can someone provide me with a decent way to do this please?

EDIT:

Here's something choroba asked me to post

diff -Naur -x '*.o' -x '*.cmd' -x '*.d' original_308/arch/arm/boot/compressed/head.S my_308/arch/arm/boot/compressed/head.S
--- original_308/arch/arm/boot/compressed/head.S    2011-10-25 07:11:12.000000000 +0200
+++ my_308/arch/arm/boot/compressed/head.S  2012-07-04 03:57:25.000000000 +0200
@@ -656,6 +656,8 @@
@       b   __arm6_mmu_cache_off
@       b   __armv3_mmu_cache_flush

So yes, it is the proper output even though gedit/geany cannot open it. UltraEdit does...

share|improve this question

2 Answers 2

up vote 1 down vote accepted

You can use the original format that creates the huge diff file which you can subsequently split into the small files. You might be interested in csplit for the splitting, or you can use a scripting language like Perl:

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

If you need the diff line in each file, add the print after the open.

share|improve this answer
    
I really don't know anything about perl, can i paste this into a mydiff.sh file and execute it in shell? Also, since this language is somewhat unreadable to me, will it generate a .patch file for every ALTERED file between the two folders? –  Shark Sep 10 '12 at 12:12
    
Yes, pasting this into your shell script or command prompt should be safe. It will create a patch file for each pair in the current working directory, for a file named a/b.c the patch will be called a_b.c.patch. I did not post a more readable version of the solution as it would take much more space. –  choroba Sep 10 '12 at 12:44
    
It didn't work for me :/ does it traverse the directory tree and call diff for each file there or what? I don't even know why it doesn't work... And please take up some more space. –  Shark Sep 10 '12 at 13:13
    
@Shark: It operates on the file created by diff -drupN .... Have you created it? –  choroba Sep 10 '12 at 13:32
    
I have this in my folder: original_308, my_308, your_diff.sh, kernel.patch. I have found there to be 231 different files, i want those 231 .patch files to end up in a patches/ folder somehow or just following the folder structure. –  Shark Sep 10 '12 at 13:48

I have wrote a small Perl script to patch the files. This script is very basic, which goes through the directories recursively and fetch the file and creates a diff.

Usage: script_name.pl <source_dir> <dest_dir> <dir_2_create_diffs>

testpatch.pl

#!/usr/bin/perl

use File::Find;
my $source = $ARGV[0];
my $dest = $ARGV[1];
my $pathdir = $ARGV[2];

unless (defined $ARGV[2]) { print "Usage: $0 <source> <dest> <patch_directory>\n"; exit 0; }
my @alldir;
find sub {
     return if -d;
     push @alldir, $File::Find::name;
}, "$source";
for my $path ( @alldir) {
     my @tmp = split ("/",$path); my $rmt_dir = shift(@tmp); 
     my $fpath = join("/",@tmp);  my $fn = $tmp[-1];
     pop(@tmp); my $strp_path = join("/",@tmp);
     `mkdir -p $pathdir/$strp_path` unless( -d "$pathdir/$strp_path");
     `diff -dupN $path $dest$fpath > $pathdir/$strp_path/$fn.patch`;
}

Sample usage: $ ./testpatch.pl original_308/ tmp/ tmp1

I created sample files( header.cpp, head1.S, head.S)

  • original_308/arch/arm/boot:header.cpp
  • original_308/arch/arm/boot/compressed:head1.S head.S
  • tmp/arch/arm/boot:header.cpp
  • tmp/arch/arm/boot/compressed:head1.S head.S

After running the script, the diffs were created in a new dir "tmp1"

Output:

  • tmp1/arch/arm/boot:header.cpp.patch
  • tmp1/arch/arm/boot/compressed: head1.S.patch head.S.patch

Hope this helps.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.