Assuming your filenames don't have any whitespace and there are no subdirectories in either directory, the following will print pairs of filenames with matching MD5 sums:
join -o 1.2,2.2 <(md5sum $D1/* | sort) <(md5sum $D2/* | sort)
To get just one of the filenames, use -o 1.2
or -o 2.2
.
If filenames (or paths) might include whitespace, you'll need to be more clever.
If a single directory might have the same file with more than one name, you will also need to be more clever -- and you will need to decide exactly what to do. One possibility would be to filter out the duplicates before doing the join:
join -o 1.2,2.2 <(md5sum $D1/* | sort | uniq -w16) \
<(md5sum $D2/* | sort | uniq -w16)
DO NOT USE sum
sum
outputs a 16-bit checksum; if you have even a couple of hundred files in each directory, it is likely that you will get a false positive if you compare 16-bit checksums. md5sum
is not absolutely definitively safe, either, but the odds of a collision with 128-bit checksums is tiny. In case of doubt, and if it's really important, cmp
the files as well:
join -o 1.2,2.2 <(md5sum $D1/* | sort) <(md5sum $D2/* | sort) |
while read F1 F2; do
if cmp -s $F1 $F2; then
cp F1 $D3
fi
done
(Again, that won't work if the files might have whitespace in their names.)