58

I diff-ed 2 files and got

1c1
< 1
---
> 1

Both files contained just "1". How is this different?

7
  • post the contents of both files please ;)
    – Rinzwind
    Commented Aug 13, 2011 at 15:05
  • 6
    If you're using diff, the -u option may be more human-readable.
    – Lekensteyn
    Commented Aug 13, 2011 at 15:13
  • @Rinzwind, both files contain just the text 1, but if you want to see more look pastebin.com/byiqdie1
    – Jiew Meng
    Commented Aug 14, 2011 at 13:23
  • Sorry. It does not when I do that. There must be something different. Do a cp 1 2 (so overwrite 2) and then you can be 100%b sure they are the same ;)
    – Rinzwind
    Commented Aug 14, 2011 at 13:28
  • 4
    vimdiff file1 file2? :D
    – dylnmc
    Commented Nov 24, 2015 at 15:27

6 Answers 6

71
  • 1st line: a stands for added, d for deleted and c for changed. Line numbers of the original file appear before these letters and those of the modified file appear after the letter.

  • 2nd line: line with < are from file 1 and are different from file 2.

  • 3rd line is a divider.

  • 4th line: line with > are from file 2 and are different from file 1.

    (If you ever see = it means the lines are the same in both files)

And your problem might be whitespaces or other non-human readable characters: those trigger a difference too.

There are some options to manipulate output.

Example:

$ more 1 
test
test2
test3
$ more 2
test
test2  
test3

Contexted format:

$ diff -c  1 2
*** 1   2011-08-13 17:05:40.433966684 +0200
--- 2   2011-08-13 17:11:24.369966629 +0200
***************
*** 1,3 ****
  test
! test2
  test3
--- 1,3 ----
  test
! test2  
  test3

A ! represents a change between lines that correspond in the two files. A + represents the addition of a line, while a blank space represents an unchanged line. At the beginning of the patch is the file information, including the full path and a time stamp. At the beginning of each hunk are the line numbers that apply for the corresponding change in the files. A number range appearing between sets of three asterisks applies to the original file, while sets of three dashes apply to the new file. The hunk ranges specify the starting and ending line numbers in the respective file.

Expanding on Lekensteyn's comment about unified format (-u option of diff):

$ diff -u  1 2
--- 1   2011-08-13 17:05:40.433966684 +0200
+++ 2   2011-08-13 17:11:24.369966629 +0200
@@ -1,3 +1,3 @@
 test
-test2
+test2  
 test3

The format starts with the same two-line header as the context format, except that the original file is preceded by --- and the new file is preceded by +++. Following this are one or more change hunks that contain the line differences in the file. The unchanged, contextual lines are preceded by a space character, addition lines are preceded by a plus sign, and deletion lines are preceded by a minus sign.

Some useful options:

  • -b: Ignore changes in the amount of white space.

  • -w: Ignore all white space.

  • -B: Ignore all blank lines.

  • -y: Output in 2 columns.

4
  • How do I check if there are any hidden characters? Is there anyway to ignore hidden characters (maybe just excluding newlines & tabs?) I suppose most hidden characters are accidental?
    – Jiew Meng
    Commented Aug 14, 2011 at 13:29
  • I put in some useful options (copied from man diff ;) )
    – Rinzwind
    Commented Aug 14, 2011 at 13:32
  • I notice using the -b flag works. Hmm I dont see difference in whitespace in gedit :)
    – Jiew Meng
    Commented Aug 15, 2011 at 0:35
  • @JiewMeng Run od -x1z on both files and compare od output. It should find any hidden differences between the files.
    – lgarzo
    Commented Sep 3, 2013 at 12:59
7

I find od (octal dump) to be handy when comparing files with non-printable characters (particularly files which diff decides that are "binary" and thus tells you only that they do differ).

In the example below, I create a pair of files that could be like the original ones, then do a diff with the original output; next I do diff on a couple of different od outputs.

$ echo 1 > 1
$ echo "1 " > 2
$ diff 1 2
1c1  
< 1  
- ---  
> 1
$ od -c 1 > 1.od
$ od -c 2 > 2.od
$ diff 1.od 2.od
1,2c1,2
< 0000000   1  \n
< 0000002
---
> 0000000   1      \n
> 0000003
$ od -Ax -c -t x1 1 > 1.od
$ od -Ax -c -t x1 2 > 2.od
$ diff 1.od 2.od
1,3c1,3
< 000000   1  \n
<         31  0a
< 000002
---
> 000000   1      \n
>         31  20  0a
> 000003
3

One of the files might be in a DOS/Windows format and the other one in UNIX format. So run the following command to convert DOS to UNIX:

dos2unix <file1> <file2>

In my case, after I did this the diff was all good!

1

It's very likely that a non-printing character is lurking around in one of the lines. Just pipe the output into cat -t to display any non-printing characters:

diff file1 file2 | cat -t
0

Not sure if this helps with hard-to-find whitespace characters, but you may want to use wdiff, a front-end to diff, which is handy for diffing. You can install it using:

sudo apt install wdiff
0

In addition to Rinzwind's explanation, the GNU Diffutils documentation provides a more concise and clear description of Unified Format:

2.2.2.2 Detailed Description of Unified Format

The unified output format starts with a two-line header, which looks like this:

--- from-file from-file-modification-time
+++ to-file to-file-modification-time

The timestamp looks like ‘2002-02-21 23:30:39.942229878 -0800’ to indicate the date, time with fractional seconds, and time zone. The fractional seconds are omitted on hosts that do not support fractional timestamps.

You can change the header’s content with the --label=label option. See Showing Alternate File Names.

Next come one or more hunks of differences; each hunk shows one area where the files differ. Unified format hunks look like this:

@@ from-file-line-numbers to-file-line-numbers @@
 line-from-either-file
 line-from-either-file…

If a hunk contains just one line, only its start line number appears. Otherwise its line numbers look like ‘start,count’. An empty hunk is considered to start at the line that follows the hunk.

If a hunk and its context contain two or more lines, its line numbers look like ‘start,count’. Otherwise only its end line number appears. An empty hunk is considered to end at the line that precedes the hunk.

The lines common to both files begin with a space character. The lines that actually differ between the two files have one of the following indicator characters in the left print column:

+’: A line was added here to the first file.

-’: A line was removed here from the first file.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .