13

Are there any Linux/Unix tools which find all the files in one directory not present in another? Basically I'm looking for diff which works on the output of ls.

Short and sweet scripts are also appreciated.

21

diff does this already:

diff dir1 dir2

Example output:

Only in dir1: some_file.txt
Only in dir1: some_other_file.txt
Only in dir2: third_file.txt
| improve this answer | |
  • 5
    This is good. One gripe: diff is actually running on each of the files that are in both. Is there an obscure option to just run against file names (I may have missed it)? Otherwise, I suggest diff dir1 dir2 | grep "Only" – Willi Ballenthin Sep 1 '10 at 16:12
  • wow this just save me many minutes of bash scripting thanks – user5359531 Feb 18 at 12:51
10

Bash:

diff <(cd dir1; ls) <(cd dir2; ls)

Compare only the filenames - not the contents of the files.

| improve this answer | |
4

Like people told you here, you can use DIFF in various usage variations. Or you just use dirdiff instead, which is meant for what you're trying! :-)

But if you want to keep some directories in sync then you really should take a look on rsync.

Regards

| improve this answer | |
3

If you are wanting to do this through all sub directories as well, a good way to do it is:

diff --brief -r dir1/ dir2/

I prefer using brief, but you can leave that out if you want.

| improve this answer | |
1

for i in $(ls -1 directory1); do if (test -f directory2/$i) then echo $i; fi; done

| improve this answer | |
0

This works..

ls -a1 /dir1 | sort > /tmp/1
ls -a1 /dir2 | sort > /tmp/2
diff /tmp/1 /tmp/2
| improve this answer | |
0

untested:

find /dir/A -printf "%P" | while read f; do
  if [ ! -e "/dir/B/$f" ]; then
    echo $f
  fi
done
| improve this answer | |
0

Dennis Williamson had a good answer, but I needed to do this recursively. GNU findutils 4.7.0 doesn't sort its output, so here's what I used

diff <(cd $dir1; find | sort) <(cd $dir2; find | sort)

To do this only one way, and produce a list of files, I used this:

diff <(cd $dir1; find | sort) <(cd $dir2; find | sort) \
| grep '< ./' | sed "s,< ./,$dir1/,"

For this to work properly, neither $dir1 nor $dir2 should include the trailing slash.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.