Super User is a question and answer site for computer enthusiasts and power users. 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

Doing: diff -r -X <ignore-list> <src-dir> <dest-dir>

doesn't seem to make diff ignore entries in <ignore-list> if they are of the form <dir>/<file>.

Entries of the form <file> do however get considered. This is a problem since I might have multiple files named <file> in different sub-directories, some of which I don't want ignored.

There doesn't seem to be much information regarding pattern syntax in the manpage for diff either. From what I can tell, it's just the base-name of a file that is considered by diff (see if you're interested).

share|improve this question
up vote 16 down vote accepted

Listing directories should work; e.g., here's what I've used in a script (assuming gnu diff),

diff -r \
   --exclude="*~" \
   --exclude=".svn" \
   --exclude=".git" \
   --exclude="*.zip*" \
   --exclude="*.gz" \
   --exclude="*.tar" \

...which ignores contents of .svn and .git dirs, but also individual files named *.zip/*.gz/etc.

Edit: In order to filter paths of the form dir_a/file1 but still diff files with the same basename, such as dir_b/file1 or dir_a/b/file1, then a list of files to diff would have to be generated (for example, using find), and the file to compare derived from these paths; e.g., given

$ find ONE TWO -type f -print 

you generate the list of files to compare, excluding for example */a/2.txt but still comparing other files named 2.txt. Just "find" all files except ONE/a/2.txt (a regexp can also be used here, such as .*/a/2.txt)

$ find ONE -type f \( ! -regex 'ONE/a/2.txt' \) \
    -exec bash -c 'diff -q "${1}" "${2/ONE/TWO}"' - {} {} \;  

which in effect ignores ONE/a/2.txt (and TWO/a/2.txt), but still compares the other files named 2.txt:

diff -q ONE/a/1.txt TWO/a/1.txt
diff -q ONE/a/b/2.txt TWO/a/b/2.txt

Edit: Or, more fun with find (additional fun left as an exercise for the reader), select the files or directories to exclude and then diff everything else:

$ find ONE \( -regex 'ONE/a/2.txt' -o -name b  -prune \)  \
    -o -type f -exec bash -c 'echo diff -q "${1}" "${2/ONE/TWO}"' - {} {} \

The above example excludes the specific file "{top}/a/2.txt", any directory named "b", and everything else is diff'd. (Instead of simple "-name b" you could also use "-regex '.*/b'" - note, no trailing "/".)

share|improve this answer
Thanks but I think you're missing the point. The only support there seems to be is when you use a 'base-name'. That could be the name of a directory or a file. In either case, diff ignores what you've asked for. The problem arises when you use paths. For example, I can't get diff to ignore /an/absolute/path/to/a/file or ./a/relative/path/to/a/file. – Ash Sep 13 '13 at 6:52
diff --exclude="/this/specific/file/that/im/explicitly/pleading/you/to/ignore". It won't work. – Ash Sep 13 '13 at 6:54
correct, exclude patterns are matched against the files' basename (as per…); paths will not work (as in foo/bar.txt). To do that, you will likely have to run find to generate the list of filenames, and derive the path to the file to compare. – michael_n Sep 14 '13 at 11:17
updated answer to include example excluding file paths from the diff, instead of just using basename – michael_n Sep 14 '13 at 11:46
Okay, I see what you're proposing but there appears to be a problem. I need to consider directories as well, not just files (i.e -type f). Now, while you can still prune out certain files using regexp with find, if the input to diff contains a directory, it will go through and compare files within that directory and some of these files might need to be you're back to square 1. – Ash Sep 16 '13 at 4:26

I had the same problem so I created a patch to diff. The patch has yet to be accepted, but you can build your own version of diff with the patch or install on Arch Linux with an AUR package.

Here is the diff patch.

share|improve this answer

You must log in to answer this question.

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