Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. It's 100% free, no registration required.

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 currently try to monitor two directories and subdirectories for changes in files. The directories contain the same set of files, some of them are changed. So I thought I might use the diff command to create a list of changed files with the line numbers and changes. I need this list to further process it by another script.

Since you can use the diff -r option to recursively check for changes, I tried to format the output to suit my needs. I can't use the default multiline output, but want to have the following:


my first line
my second line
my third line


my first line
my changed second line
my third line

My desired output would either look like:

file_2:2:my changed second line

or (if that is easier):

file_1:2:my second line
file_2:2:my changed second line

I managed to produce the output without the filename with the following parameters:

diff -qbBwr --unchanged-line-format="" --old-line-format=":%d:%L" --new-line-format=":%dn:%L"  file_1 file_2

which results in

:2:my second line
:2:my changed second line

But there are two problems:

  • The lfmt option does not work with the recursive option -r
  • I do not get the filename

So finally the question is:

Does anybody know how to diff two directories in a way that I get the desired output from above?

share|improve this question
up vote 2 down vote accepted

I think this ought to do what you need:

diff -r -U0 a/ b/ | awk '/^+++ / {filename=$2; next} /^@@ / {split($3,a,","); line=substr(a[1],2)} /^+/ {text=substr($0,2); print filename ":" line ":" text; line++}'

Basically, it does an ordinary recursive diff, and then discards the bit you don't want. awk is cool for stuff like this.

diff -U0 gives output like this:

--- a   2014-07-01 17:05:46.257447351 +0100
+++ b   2014-07-01 17:05:56.157524562 +0100
@@ -2 +2 @@
-my second line
+my changed second line

The awk script takes the filename from the +++ line, the line number from the @@ line, and the text from the + line, and then prints them with the colons you wanted:

file_2:2:my changed second line

EDIT: I noticed a script error if two lines together were edited. Fixed now.

share|improve this answer
Thank you very much for that script and the explanation, i already thought about using awk or similar, just am not too good at it. I am wondering on thing though: What version of awk are you using, sind the script produces no output for me (i am using GNU Awk 4.0.1) – Olli Jul 2 '14 at 11:45
I have GNU Awk 4.1.1 – ams Jul 2 '14 at 11:48
Perhaps the diff produced nothing? – ams Jul 2 '14 at 11:49
the problem was that my shell (bash) needs quoting of the + signs in your script, otherwise it fails to match correctly. – Olli Jul 2 '14 at 12:42

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.