Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I'd like to print a list of lines where the first word in two files is identical, and the rest of the words are not. Some complicated mess with comm, grep and cut would be possible, but hopefully there's a simpler way.

Edit: I've managed to slap together some working code. Example tests:

$ cat file1
a 1 E
b 2 F
c 3 G

$ cat file2
a M X
b 2 Y
c 3 G

$ difff 1 file1 file2 # Differences in fields 2+3
< a 1 E
< b 2 F
> a M X
> b 2 Y

$ difff 1-2 file1 file2 # Differences in field 3 only
< b 2 F
> b 2 Y

Edit 2: The speed is now bearable (compares two files of 1800 and 8700 lines in half a second).

share|improve this question
Is there some reason why a traditional (or unified) diff won't do the job? – draeath Sep 19 '11 at 16:19
Are the first columns of file1 and file2 identical? Have you considered join and paste? (I'm not going to offer more precise suggestion because I don't understand the requirements.) – Gilles Sep 19 '11 at 23:56
@draeath: Because if would also show lines which start with different words. That's what I want to exclude. As you can see from the diff above, the lines starting with baz and bay are not included, even though they are different. – l0b0 Sep 20 '11 at 6:40
up vote 2 down vote accepted

Assuming that both file1 and file2 are sorted (otherwise join won't work):

diff -u file1 file2 |
  grep -E "^[+-]($(echo $(join -o0 file1 file2) | tr ' ' '|'))"


The join command will output the join field that occurs in both files (i.e. the first word of the line which is the same in both files), one on each line. We echo this though tr, replacing all spaces with a pipe (|). The reason for doing the slightly convoluted echo (and not just piping the result from join directly through tr) is that the output from join will have a newline at the end of it which we do not want to replace with a pipe.

For the example files (the ones that were originally given by the OP before his edit of the question), the join, echo, tr thingy will produce bar|foo. This is the used as part of an extended regular expression in grep -E to filter through the output of diff -u.

The output of the command line is:

-bar c d
+bar x y
share|improve this answer
Didn't use join, but your answer pointed in the right direction. – l0b0 Sep 20 '11 at 14:39

Your Answer


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.