Comparison of 2 files in UNIX

Hi, There are two files in UNIX system with some lines are exactly the same, some lines are not.
I want to compare these two files.The 2 files (both the files have data in Column format )should be compared row wise and any difference in data for a particular row should lead to storage of data of second file in another new third file.
i.e here we are assuming second file( file 2 ) to be updated version of first file (file 1) and any difference in row wise matching would lead to storage of the updated /modified data in another third file .

:frowning:
Please help me ASAP:confused::frowning:

check if diff can solve your problem

hi yogesh diff is NOT solving the problem ( i have tried that)..
bcoz the output apart from giving the difference in file contents is also displaying line numbers and other special kind of instructions ...

we got to pick up only the modified data from this third file .. so diff doesn't work out here properly
for eg below is one such display

1c1,2
< 1|2|2|2|4|3
---
> 1|2|3|2|3|4
>

Thank you

do let us know in case of any other options:(

So then pipe the diff output through a filter which just selects the changes you interested in, say by looking for lines either begining with < or >.

Porter here NOT all lines begin in same way/with same special characters

even i tried following the same stuff ( as suggested by u ) long time back

diff file1 file2 > diff_file.txt
cut -d"|" -f1 diff_file.txt|egrep -v ",|-|>|<" > final.txt

field 1( f1) was the desired field which was to be picked up from the diff_file.txt file .. but again problem is that the diff_file.txt contained the line numbers in some places Also
(note: diff_file.txt has huge number of rows of data) ,so these unwanted line numbers which lie in same column as the field 1 data also gets picked up with the field1 data

eg line numbers like 4d3,5a5 etc
Note :file 1 n file 2 contains numbers as data
so i want final.txt file to have pure numbers only
:confused:

Perhaps grep might help.

grep -vf file1 file2 > file3

Eg.

[/tmp]$ cat file1
1 2
2 3
3 4
4 5
5 6
[/tmp]$ cat file2
1 2
2 4
3 6
4 5
5 6
[/tmp]$ grep -vf file1 file2 > file3
[/tmp]$ cat file3
2 4
3 6
[/tmp]$

Hey Vino thanks a lottt !!!!! ..but again ur suggestion is applicable only when both the files have certain contents which are unique to that particular file and NOT found in other one ...

for eg
two files file3 having contents
bat
mat
rat

and file4 having contents
bat
rat
hat

in such case grep -vf file3 file4
would display only "hat" and not rat because rat is present there is file 3
:frowning:
but our criteria is that
rat as well as hat should be displayed as we are matching the column contents row wise ONLY.. so here the values at second and third place of file 4 differ from those of file 3 so accordingly i want rat and hat to be displayed
any idea :confused:

You can turn around the files.:stuck_out_tongue:

grep -vf file4 file3

well i tried that it is displaying
grep -vf file4 file3

mat

but criteria is that
i shud be getting rat and hat ( file 4 is assumed as updated version of file3 by the user concerned) as on comparing the 2nd and 3rd place values of file 4 do NOT match with the 2nd and 3rd place values of file3

file3
bat
mat
rat

file4
bat
rat
hat
:confused:

Can you provide one sample input file each for file1 and file2. Also show us what you want in the resulting file3.

for eg there are two files to be compared
file1
1111 | universe
2222 |good
3333 |good
4444 |good

file2
1111 | universe
3333 |universe
2222 |good
4444 |good

the contents of both the files will be compared row wise( i.e. row 1 content of file1 to be compared with row 1 content of file2 and so on)

if there is any difference/change in values (it can be numbers or those words) of corresponding rows then the script will pick up the numbers of field one(f 1) from file2 NOT file1.

like here the script should pick up 3333 and 2222 ( 2nd and 3rd positions values of file2) from file2 and redirect it to another to another third file.:confused:

You could read in the files simultaneously by opening them in different file descriptors, then use "read" to read from these descriptors.

exec 3</path/to/file1
exec 4</path/to/file2

typeset chBuffer1=""
typeset chBuffer2=""

while read -u3 chBuffer1 ; do
     read -u4 chBuffer2
     if [ <put your tests using chBuffer1 and chBuffer2 here> ] ; then
          ....
     else
          ....
     fi
done

exec 3<&-
exec 4<&-

bakunin

Would sdiff help you?

Hi.

Here is a shell driver script:

#!/usr/bin/env sh

# @(#) s2       Demonstrate perl line reading, comparison.

set -o nounset
echo

debug=":"
debug="echo"

## Use local command version for the commands in this demonstration.

echo "(Versions displayed with local utility \"version\")"
version >/dev/null 2>& 1 && version bash perl

echo

echo " Data files data1 data2:"
cat data1
echo
cat data2

echo
echo " perl script output, filtered:"
./p1 data1 data2 |
cut -d"|" -f1

exit 0

which calls a perl script:

#!/usr/bin/perl

# @(#) p1       Demonstrate display of line-by-line differences.

use warnings;
use strict;

my ($debug);
$debug = 1;
$debug = 0;

my ( $f1, $f2, $file1, $file2, $line1, $line2, $EOF1, $EOF2 );
my ($lines) = 0;

$EOF1 = $EOF2 = 0;

$file1 = shift || die " usage: $0 file_1 file2\n";
$file2 = shift || die " usage: $0 file_1 file2\n";

open( $f1, "<", $file1 ) || die " Cannot open file $f1\n";
open( $f2, "<", $file2 ) || die " Cannot open file $f2\n";

while (1) {
  if ( not( $line1 = <$f1> ) ) {
    $EOF1 = 1;
  }

  if ( not( $line2 = <$f2> ) ) {
    $EOF2 = 1;
  }

  if ( $EOF1 + $EOF2 != 0 ) {
    print STDERR " Checking EOF on both files.\n" if $debug;
    if ( $EOF1 == 0 ) {
      print STDERR " Note - file $file1 has extra lines, stopping.\n";
    }
    if ( $EOF2 == 0 ) {
      print STDERR " Note - file $file2 has extra lines, stopping.\n";
    }

    # In any case, this is our last read
    last;
  }

  $lines++;
  if ( index( $line1, $line2 ) != 0 ) {
    print $line2;
  }
}

print STDERR " ( Complete pairs of lines read: $lines )\n";

exit(0);

Producing from your data on files data1 and data2:

% ./s2

(Versions displayed with local utility "version")
GNU bash 2.05b.0
perl 5.8.4

 Data files data1 data2:
1111 | universe
2222 |good
3333 |good
4444 |good

1111 | universe
3333 |universe
2222 |good
4444 |good

 perl script output, filtered:
 ( Complete pairs of lines read: 4 )
3333
2222

cheers, drl

Just to verify, your two files will always have the same number of lines? If not, there is no way to make the comparison.

Hi.

My impression is that this is a row-to-row comparison, so that if you run out of rows (lines) on either file prematurely, you just stop. It's not like diff, where one seeks back and forth vertically to see what was added, deleted, or changed.

Do you see it differently? [pun intended] ... cheers, drl

:smiley:
I'm just trying to verify that the original poster has thought the problem through. Your code will work correctly for the stated problem. But, if there are additions or deletions along with his updates, and the additions are not at the end of the file2, then he's back to a manual process of trying to figure out what changed between the files. In most situations, there is a key field to match on. But that doesn't seem to be the case here.

hey DRL thanks a ton!! for your help ..
but again as per the requirement of boss it has to be done using Unix shell script ( plsql if required):frowning:

the files file1 and file2 won't necessarily have the same number of rows .
file1 and file2 have column values of a specific oracle table exported and stored in Unix system on regular basis .
the idea is two compare the contents of the files of previous day and current day ( for e.g file1 is previous day's file and file2 is current day's file) i.e. we got to do row wise comparison of file and detect if there is change in any particular row value if any particular row in file2 (say for e.g row number 3 ) differs from row number 3 of file1 ... then the script should pick up the row num 3 value from file 2 and re-direct it to another third file.

but since we got to verify previous day's and current day's records .. so even if both the files do not have same number of lines ... it won't be a problem as our target is to compare whether a particular row which had some value until yesterday still has the same value today or has it been changed.. in such case the script can compare until it reaches the row end of file1 .
hope i m clear with my question

well i came across options ( thanks to this forum) but following code i tried
comp1=$(cat file1 | cut -d"|" -f1,2)
comp2=$(cat file2 | cut -d"|" -f1,2)
for str in ${comp2[]}
do
count=0
while (( $count < ${#comp1[
]} ))
do
if [[ $str != ${comp1[count]} ]]
then

cat file2 | grep $str >> find.txt
fi
count=`expr $count+1`
done
done

Note:
file1
1111|universe
2222|good
3333|good
4444|good

file2
1111|universe
3333|universe
2222|good
4444|good

and in output i should get

3333|universe
2222|good

as row 2 and 3 of file2 are different from file1 so these 2 lines would be picked up from file2

i am not getting desired result
any suggestion how can the code be modified

:confused:

try this,

perl -e ' open(FILE, "<", "f1"); while(<FILE>) { $fileHash{$_} = $. ; } close(FILE); open(FILE, "<", "f2"); while(<FILE>) { print $_ if ( $fileHash{$_} != $. ); } close(FILE); '