I would have made this a comment on Marki's answer but it would have been too long. There is a caveat to his solution:
Parsing output of ls
or find
are alike non-robust and liable to breakage. Here is an example:
$ mkdir dir{1,2}
$ touch !$/file{1..5}
touch dir{1,2}/file{1..5}
$ mkdir dir1/$'\n'.
$ touch !$/whoops
touch dir1/$'\n'./whoops
$ touch dir2/whoops
$ touch dir1/onlyin1
$ touch dir2/onlyin2
$ comm <( cd dir1 ; find . | sort ) <( cd dir2 ; find . | sort )
.
.
./
./
./file1
./file2
./file3
./file4
./file5
./onlyin1
./onlyin2
./whoops
(I'm using comm
for three-way text comparison rather than vimdiff
so I can copy-paste more easily; the result is the same in vimdiff
.)
You see that this incorrectly displays that the file whoops
is in both directories, when in fact one of those whoops
files is in in a subdirectory of dir1
which contains a newline in its name.
Normally people don't put newlines in filenames or directory names, and the vimdiff
answer should work on any other special characters (though I haven't tested). However it's still something to be wary of. If you are going to put this into a script or into production code of any kind, please work on making it more robust, e.g. by walking both directory trees properly and comparing them.