Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

How can I get diff to show only added and deleted lines? If diff can't do it, what tool can?

share|improve this question
    
You need to better define what you mean by added and deleted. Specifically, can a line change? If so, how do you want a changed line to be handled? If you are doing strictly line oriented checking, a line changing is identical to the old line being removed and the new line being added. For example, how should it handle a line that's split in two? As two 1 line changed? 2 lines changed? 1 line removed and 2 lines added? Unless you can guarantee that lines will never change, just be added and deleted, I think this is doomed to fail without better definitions. –  Christopher Cashell Apr 13 '12 at 16:11
add comment

6 Answers

Another way to look at it:

Show lines that only exist in file a:

comm -23 a b

Show lines that only exist in file b:

comm -13 a b

Show lines that only exist in one file or the other:

comm -3 a b | sed 's/^\t//'
share|improve this answer
    
just wanted to add that both files needs to be sorted (case sensitive) for this solution to produce correct results –  marmor Apr 28 at 10:29
add comment

comm might do what you want. From its man page:

DESCRIPTION

Compare sorted files FILE1 and FILE2 line by line.

With no options, produce three-column output. Column one contains lines unique to FILE1, column two contains lines unique to FILE2, and column three contains lines common to both files.

These columns are suppressable with -1, -2 and -3 respectively.

Example:

[root@dev ~]# cat a
common
shared
unique

[root@dev ~]# cat b
common
individual
shared

[root@dev ~]# comm -3 a b
    individual
unique

And if you just want the unique lines and don't care which file they're in:

[root@dev ~]# comm -3 a b | sed 's/^\t//'
individual
unique

As the man page says, the files must be sorted beforehand.

share|improve this answer
add comment

Visual comparison tools fit two files together so that a segment with the same number of lines but differing content will be considered a changed segment. Completely new lines between matching segments are considered added segments.

This is also how sdiff command-line tool works, which shows a side-by-side comparison of two files in a terminal. Changed lines are separated by | character. If a line exists only in file A, < is used as the separator character. If a line exists only in file B, > is used as the separator. If you don't have < and > characters in the files, you can use this to show only added lines:

sdiff A B | grep '[<>]'
share|improve this answer
add comment

No, diff doesn't actually show the differences between two files in the way one might think. It produces a sequence of editing commands for a tool like patch to use to change one file into another.

The difficulty for any attempt at doing what you're looking for is how to define what constitutes a line that has changed versus a deleted one followed by an added one. Also what to do when lines are added, deleted and changed adjacent to each other.

share|improve this answer
    
My thoughts exactly. What percentage of characters in a line has to change in order to consider it a new one instead of a modification of the original? Technically even if you have one character in common, you could consider it a "change" instead of a deletion and insertion. –  Kamil Kisiel Sep 25 '09 at 18:35
1  
It's been a long time since I've looked at the diff sources, but I seem to remember all manner of gyrations to keep track of where two files match to stay in synch and I think there's a threshold for giving up based on how far apart the lines are. But I don't remember any intra-line matching except for (optionally) collapsed white space or ignoring case. Or (perhaps) words to that affect. In any case, it's all about patch and "vgrep" just comes along for the ride. Maybe. On Tuesday. –  Dennis Williamson Sep 25 '09 at 18:54
add comment

Thanks senarvi, your solution (not voted for) actually gave me EXACTLY what I wanted after looking for ages on a ton of pages.

Using your answer, here is what I came up with to get the list of things changed/added/deleted. The example uses 2 versions of the /etc/passwd file and prints out the username for the relevant records.

#!/bin/bash
sdiff passwd1 passwd2 | grep '[|]' | awk -F: '{print "changed: " $1}'
sdiff passwd1 passwd2 | grep '[<]' | awk -F: '{print "deleted: " $1}'
sdiff passwd1 passwd2 | grep '[>]' | awk -F\> '{print $2}' | awk -F: '{print "added: " $1}'
share|improve this answer
add comment

That's what diff does by default... Maybe you need to add some flags to ignore whitespace?

diff -b -B

should ignore blank lines and different numbers of spaces.

share|improve this answer
1  
No, it shows CHANGED lines as well (lines that have a character or four different). I want lines that only exist in left or right. –  C. Ross Sep 25 '09 at 13:35
1  
You could argue that the differing versions of a CHANGED file each exist only in left or right. –  markdrayton Sep 25 '09 at 14:28
    
There's no way for diff (or any other tool) to reliably tell what's a change, and what's a deleted line being replaced by a new line. –  Cian Sep 25 '09 at 15:07
    
Technically, diff treats a "changed" line as if the original line was deleted and a new line was added...so technically it is showing you only added and deleted lines. –  KFro Sep 25 '09 at 17:33
add comment

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.