Beefy Boxes and Bandwidth Generously Provided by pair Networks
Your skill will accomplish
what the force of many cannot
 
PerlMonks  

Dealing with diff command within perl

by surajsam (Initiate)
on Nov 25, 2011 at 23:57 UTC ( [id://940143]=perlquestion: print w/replies, xml ) Need Help??

surajsam has asked for the wisdom of the Perl Monks concerning the following question:

This could be more of unix question too. Since I am dealing with 'diff' within a perl script, thought of asking here.

foreach $f (@isect) { print "diffing file $f \n"; system("diff -r $some_dir/$f $other_dir/$f" ); }

isect array contains common elements of two other arrays (directories). when I do a diff between two directories for all the elements of isect, I want to ignore the identical elements (files). I want the diff to report only those files that differ.

for example one sample output would look like, as follows -

Intersect Array = 4 3 diffing file 4 4d3 < 1111 diffing file 3

In the above example, I don't want "diffing file 3" to be printed, since 'file 3' is an identical file between two arrays. I want to ignore files with no diff. I was looking for a switch for the diff command and did not find any. BTW, I don't have Diff.pm in my environment and that possibility is ruled out. Appreciate any help

Replies are listed 'Best First'.
Re: Dealing with diff command within perl
by Corion (Patriarch) on Nov 26, 2011 at 09:20 UTC

    First of all, you can easily install Algorithm::Diff yourself, see Yes, even you can use CPAN.

    Second, if you read diff, you will find that the exit status for identical files is 0 and otherwise nonzero. If you read system, you will find that it returns the exit status of the program. So you might just want to use that.

      I dare to bet that speedwise, diff the command line program will run circles around Algorithm::Diff.

        First of all, thanks Monks for your suggestions. This is what worked for me-

        use File::Compare; open( DIFFFILE, ">> $diffFile" )|| die " cannot open $diffFile +file !!\n"; print DIFFFILE "Modified Files \n"; print DIFFFILE "<br>\n"; print DIFFFILE "=========== \n"; print DIFFFILE "<br>\n"; if (scalar(@modarry) >= 1) { foreach $f (@modarry) { print DIFFFILE "<br>\n"; print DIFFFILE "$f \n"; print DIFFFILE "<br>\n"; } }elsif (scalar(@modarry) < 1) { print DIFFFILE "\t\n None \n"; print DIFFFILE "<br>\n"; } close (DIFFFILE); foreach $f (@modarry) { @the_string=`diff -r $some_dir/$f $other_dir/$f`; open( DIFFFILE, ">> $diffFile" )|| die " cannot open $diffFile + file !!\n"; print DIFFFILE "<br>\n"; print DIFFFILE "File being diff'd: $f \n"; }

        use File::Compare, to get the list of modified files between two dirs, then run the diff command. Not efficient but it did work

Re: Dealing with diff command within perl
by jethro (Monsignor) on Nov 26, 2011 at 01:40 UTC

    If you use backticks instead of system() you can store the output of diff into an array. If that array is empty, the files are identical. If not, print your header and the array.

      ... and when you get an empty file in one directory and a DVD image in the other, you're in trouble :) Better to use Corion's idea and throw the output away:
      $ret = system("diff >/dev/null -r $some_dir/$f $other_dir/$f"); if(0 == $ret) { # files are the same } elsif(1 == $ret) { # files differ } else { # Error from diff }
      That would still write the whole DVD image to /dev/null in my imaginary case even though it's clear after the first line that there are in fact differences. If that's a real possibility, something like your idea but without reading the whole diff would probably be faster:
      open(my $fh, '-|', "diff -r $some_dir/$f $other_dir/$f") or die "diff +: $!"; my $diff = <$fh>; close $fh; if($diff) { # there were diffs }
      After the first line of output, diff gets a SIGPIPE because we closed it output and dies. One should probably check $? for errors from diff there, too.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://940143]
Approved by planetscape
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others studying the Monastery: (6)
As of 2024-03-28 18:34 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found