969

If I want find the differences between two directory trees, I usually just execute:

diff -r dir1/ dir2/

This outputs exactly what the differences are between corresponding files. I'm interested in just getting a list of corresponding files whose content differs. I assumed that this would simply be a matter of passing a command line option to diff, but I couldn't find anything on the man page.

Any suggestions?

Chris Stryczynski
  • 30,145
  • 48
  • 175
  • 286
Mansoor Siddiqui
  • 20,853
  • 10
  • 48
  • 67

10 Answers10

1394

Try:

diff --brief --recursive dir1/ dir2/

Or alternatively, with the short flags -qr:

diff -qr dir1/ dir2/

If you also want to see differences for files that may not exist in either directory:

diff --brief --recursive --new-file dir1/ dir2/  # with long options
diff -qrN dir1/ dir2/                            # with short flag aliases
Mateen Ulhaq
  • 24,552
  • 19
  • 101
  • 135
Mark Loeser
  • 17,657
  • 2
  • 26
  • 34
  • 29
    Nice. But shorter is `diff -qr dir1/ dir2/` and my extended version to `diff -qr dir1/ dir2/ | grep ' differ'` – sobi3ch Aug 07 '15 at 13:18
  • @sobi3ch your version does not report files only in one directory – skv Nov 30 '15 at 09:56
  • 1
    @skv why? It's the same command as answer. I've changed only `--brief` to it's shortcut `-q`. – sobi3ch Dec 01 '15 at 09:37
  • @sobi3ch I am no expert :) i just ran it and it only told me the difference in files not files present in only one location – skv Dec 01 '15 at 12:38
  • 3
    @skv Not exactly what the original question asked, but updating the answer to accommodate this question as well. – Mark Loeser Dec 09 '15 at 19:43
  • 1
    When I run this (`-brief -r`), I get `diff: conflicting output style options diff: Try 'diff --help' for more information. ` The -qr method (in the answer below) works ok. – Mike Maxwell Oct 23 '18 at 15:55
  • 12
    @MikeMaxwell It needs to be `--brief`. `-brief` is interpreted as `-b -r -i -e -f`, in other words as a set of flags not as a single option. – daboross Oct 25 '18 at 04:27
  • 3
    @daboross: wow, I've been using Unix/Linux for a l o n g time, and I never realized there was that distinction between '--' and '-'. (I don't think '--' existed when I got started.) Thanks for the explanation! – Mike Maxwell Oct 30 '18 at 16:37
  • @MikeMaxwell The "good" news is this is just convention. Programs can interpret them however they want. The "bad" news is, yes, this is a very common convention among almost all Unix tools. =) – River Tam Nov 06 '18 at 21:54
  • 10
    `-` options are called "UNIX options" and `--` options are called "GNU long options" according to `man ps`. `You should make every program accept long options if it uses any options, for this takes little extra work and helps beginners remember how to use the program.` source: https://www.gnu.org/software/libc/manual/html_node/Getopt-Long-Options.html, also https://www.google.com/search?q=gnu+long+options – Elijah Lynn Feb 22 '19 at 16:39
  • 1
    Use `-x` or `-X` to exclude specific files by shell patterns if needed. – ebk Jul 01 '20 at 04:02
  • 1
    @ElijahLynn that's specific to ps - Unix ps has only short options, while GNU's version additionally provides long options. In general they're just called short options and long options. Although they are just a convention - `find`, for example, uses - for long options. – Leonardo Dagnino Feb 22 '21 at 22:06
314

The command I use is:

diff -qr dir1/ dir2/

It is exactly the same as Mark's :) But his answer bothered me as it uses different types of flags, and it made me look twice. Using Mark's more verbose flags it would be:

diff  --brief --recursive dir1/ dir2/

I apologise for posting when the other answer is perfectly acceptable. Could not stop myself... working on being less pedantic.

FPC
  • 3,422
  • 1
  • 16
  • 12
  • 13
    ..so does it make sense tu put different answers with JUST a different flavour? IMHO no! Does it make sense tu combine both answers to one consistent answer? yes! ;) – sobi3ch Aug 07 '15 at 13:21
  • 1
    Just a question; what does the `q` stand for? Is it an abbreviation of something? I can't find any logic behind the `q`.. – kramer65 Nov 05 '16 at 22:26
  • 3
    @kramer65 - it is the same as "--brief", but I guess you wonder why q? Perhaps for quick? "-b" is taken by "ignore changes in the amount of white space" according to the man page. – FPC Nov 23 '16 at 10:27
  • @sobi3ch You are right, I apologise again. To my defence, I do not think I had the ability to edit the other answer at the time. – FPC Nov 23 '16 at 10:30
  • 9
    @kramer65 I believe the `q` is for `quiet`, generally meaning less verbose. – Gogeta70 Aug 15 '17 at 17:26
  • The comments here demonstrate why we should also use long options in our examples. Long options are mostly self-documenting. When one uses short options they explain what it does outside the code, but why not just put it in the code as a more readable example in the first place? The page for GNU Long Options even says `You should make every program accept long options if it uses any options, for this takes little extra work and helps beginners remember how to use the program.` source: https://www.gnu.org/software/libc/manual/html_node/Getopt-Long-Options.html – Elijah Lynn Feb 22 '19 at 17:56
  • Consider adding `--no-dereference`. – Tom Hale Aug 02 '19 at 05:09
151

I like to use git diff --no-index dir1/ dir2/, because it can show the differences in color (if you have that option set in your git config) and because it shows all of the differences in a long paged output using "less".

sobi3ch
  • 2,555
  • 2
  • 31
  • 41
Alan Porter
  • 2,339
  • 1
  • 17
  • 12
  • 46
    Neat. Who would've guessed that git can diff arbitrary directories, not just the repo against its files? – Dan Dascalescu May 06 '14 at 00:34
  • 3
    Perl script [colordiff](http://www.colordiff.org/) is very useful here, can be used with svn and normal diff. – Felipe Alvarez May 15 '14 at 02:37
  • 8
    If you comparing (like me) 2 dirs as seperate git projects/repos then you need add `--no-index` more on http://stackoverflow.com/a/1792477/473390. I've updated @alan-porter answer. – sobi3ch Aug 07 '15 at 13:30
  • 1
    I like this one, I also find that if you add `--name-status` to the command line, it will just show the file name list with "M/A/D" flags for Modified/Added/Deleted status. – gzh Feb 27 '20 at 06:24
  • 1
    It happens so that both directories are actually containing the .git folder, how can I exclude it from the compare? – Silidrone Mar 28 '20 at 16:37
57

Using rsync:

rsync --dry-run --recursive --delete --links --checksum --verbose /dir1/ /dir2/ > dirdiff_2.txt
# or same in short
rsync -nrlcv --delete /dir{1,2}/ > dirdiff_2.txt

Alternatively, using diff:

diff --brief --recursive --no-dereference --new-file --no-ignore-file-name-case /dir1 /dir2 > dirdiff_1.txt
# or same in short
diff -qrN --no-dereference --no-ignore-file-name-case /dir{1,2} > dirdiff_1.txt

They are functionally equivalent, but performance may vary depending on:

  • If the directories are on the same drive, rsync is faster.
  • If the directories reside on two separate drives, diff is faster.

This is because diff puts an almost equal load on both directories in parallel, maximizing load on the two drives. rsync calculates checksums in large chunks before actually comparing them. That groups the i/o operations in large chunks and leads to a more efficient processing when things take place on a single drive.

CodeBug
  • 571
  • 4
  • 2
  • 5
    rsync is not only faster for files on single drives, but also allowes for comparing files in subdirs, for example `rsync --options /usr /bin /var /sbin /lib /old_root` will effectively compare current root `/` (by specifying all subdirs in it) and `/old_root` (containing for example some older backup of `/`), which is something `diff -r` can't do. And if you assume that files with same size, permissions and timestamps probably have not changed, leaving out `--checksum` will provide you with **extremely fast** (if not so through) check of which files might have changed. – Matija Nalis Aug 19 '17 at 21:52
  • 2
    What is the purpose of `--delete` with `rsync`? – Tom Hale Sep 07 '17 at 16:13
  • 3
    The purpose of --delete is to delete existing files in destination-dir which are not (any longer) present in source-dir – Thomas Munk Sep 08 '17 at 09:31
  • 7
    In this case (with the `--dry-run` flag) nothing is really deleted, `rsync` only prints which files are in dir1 but not in dir2 – mata Oct 02 '17 at 07:15
  • 22
    I'd recommend putting `--dry-run` first always as to not accidentally forget it. – Dave Rager Apr 12 '18 at 19:41
  • 1
    The two (diff and rsync) actually produce slightly different results. Consider two directory trees in which testing123/A/f1 is missing, testing456/A/B/f4 is missing, and the files /A/B/C/f9 are different. diff testing123/ testing456/ produces 3 lines stating that f9, f4, and f1 differ. rsync testing123/ testing456/ produces: deleting A/f1 A/B/f4 A/B/C/f9 At least I know that f1 is missing on the left, but I still need to see why f4 and f9 differ. – DeanM Dec 08 '18 at 18:07
  • 3
    The `rsync` solution is very useful if you need to compare a local with a remote directory accessible over ssh – Francesco Frassinelli May 22 '19 at 11:52
  • 1
    `--no-ignore-file-name-case` not needed: The `--no-ignore-file-name-case` option cancels the effect of the `--ignore-file-name-case` option, reverting to the default behavior.`: from [here](https://www.gnu.org/software/diffutils/manual/html_node/Comparing-Directories.html) – Tom Hale Aug 02 '19 at 05:15
40

Meld is also a great tool for comparing two directories:

meld dir1/ dir2/

Meld has many options for comparing files or directories. If two files differ, it's easy to enter file comparison mode and see the exact differences.

Mateen Ulhaq
  • 24,552
  • 19
  • 101
  • 135
Alexander
  • 9,737
  • 4
  • 53
  • 59
  • 2
    Nice. I have written a simple perl script to perform comparison over trees but I am hitting limitations. This seems to be the ticket. – David Tonhofer May 19 '17 at 11:44
  • The only problem is that it does not lend itself to scripting since it is a graphical app. But it is nice if you don't mind the GUI! Thanks. – DeanM Dec 08 '18 at 18:14
  • 1
    I find that `meld` becomes horribly sluggish if used on large directories though. Is there anything that handles large directories better? – Popup Sep 06 '19 at 10:17
  • @Popup, not that I know of. You could find differing filenames with something like this, though: `find dir1 dir2 | cut -d/ -f2- | sort | uniq --unique` – Alexander Sep 06 '19 at 10:26
  • 2
    @Alexander - In that case I find that `meld <(find dir1 -ls ) <(find dir2 -ls)` works pretty well, using bash process substitution. (zsh's `=(command)` works even better.) – Popup Sep 10 '19 at 08:31
  • Meld directory compassion doesn't work if you're comparing deep contents of files because its done in the expectation that size and time are enough. It's actually pretty awful imo, or at least on the version that is on ubuntu. Even if i disable 'compare files based only on size and timestamp' it insists on marking modified files which are equal because they were modified at slightly different times. – i30817 Jul 01 '23 at 07:46
  • @i30817 Fair point. Here's the Meld issue tracker: https://gitlab.gnome.org/GNOME/meld/-/issues – Alexander Jul 01 '23 at 09:48
12

Channel compatriot 'billings' (of freenode/#centos fame) shared his method with me:

diff -Naur dir1/ dir2

Including the final directory forward slash doesn't matter.

Also, it appears the -u option is not available on some older/server versions of diff.

The difference in diffs:

# diff -Nar /tmp/dir1 /tmp/dir2/
diff -Nar /tmp/dir1/file /tmp/dir2/file
28a29
> TEST

# diff -qr /tmp/dir1/ /tmp/dir2/
Files /tmp/dir1/file and /tmp/dir2/file differ
todd_dsm
  • 918
  • 1
  • 14
  • 21
  • 2
    So that's `--new-file/-N` which makes diff consider missing files to be empty and `--text/-a` which causes it to consider all binary input to be text. I don't see the upsides for this particular use case. – phk Oct 07 '16 at 21:39
5

To find diff use this command:

diff -qr dir1/ dir2/

-r will diff all subdirectories too -q tells diff to report only when files differ.

diff  --brief dir1/ dir2/

--brief will show the files that dosent exist in directory.

Or else

we can use Meld which will show in graphical window its easy to find the difference.

meld  dir1/ dir2/
Community
  • 1
  • 1
Javeed Shakeel
  • 2,926
  • 2
  • 31
  • 40
  • 4
    `--brief` and `-q` are the same option. Your statement makes it sound like they are different but they aren't. – Elijah Lynn Feb 22 '19 at 16:36
4

Diffoscope is a great command line based directory diff tool.

I especially like about it that it can diff into files:

It will recursively unpack archives of many kinds and transform various binary formats into more human readable form to compare them. It can compare two tarballs, ISO images, or PDF just as easily.

It will not only tell you which files differ, but also how they differ.

nh2
  • 24,526
  • 11
  • 79
  • 128
2

You can also use Rsync and find. For find:

find $FOLDER -type f | cut -d/ -f2- | sort > /tmp/file_list_$FOLDER

But files with the same names and in the same subfolders, but with different content, will not be shown in the lists.

If you are a fan of GUI, you may check Meld that @Alexander mentioned. It works fine in both windows and linux.

Fábio
  • 771
  • 2
  • 14
  • 25
2

To report differences between dirA and dirB, while also updating/syncing:

rsync -auv <dirA> <dirB>
Mateen Ulhaq
  • 24,552
  • 19
  • 101
  • 135
Kickaha
  • 3,680
  • 6
  • 38
  • 57
  • 1
    While it may work, using `rsync` is adding a layer of complexity, because now you need that dependency. It is a nice collateral, but is uses a little more than just linux in my opinion. – Lomefin Dec 27 '20 at 18:38
  • 1
    @Lomefin I don't see how `rsync` is less **Linux** than `diff`. @Kickaha You definitely want a backup of your target directory, before launching that command. – Mogens TrasherDK Dec 28 '20 at 01:25