6

I have lots of photos from the web I’d like to add GPS exif data to, but I rely on removing duplicates by using comparison tools like cmp, md5sum andduff.

If I edit the exif data, then no tools I know of will recognize duplicate images. I’m looking for a tool (or reliable 1-line pipeline command) that can either:

  • (preferred) generate a digest that is only based on the body and not any metadata
  • report 2 images as identical pixel-for-pixel

Does such a tool exist? (Or is there any article that elaborates on why it is a problem not worth solving?)

Further info

The reason I prefer a digest over a black-box duplicate checker is that I like to create flat .txt files as a database of other interesting information about pictures (e.g. ranking images).

2
  • 2
    Strictly EXIF data is Metadata not a header as it can potentially occur at locations other than the start of the file. Commented Jul 9, 2018 at 0:38
  • The reason exiftool doesn't solve the problem is that it will not allow you to delete specific metadata elements - notably FileModifyDate, FileAccessDate, FileInodeChangeDate, Directory and ModifyDate. This is probably because they represent physical aspects of the file rather than characteristics of the photograph therein. There may be others too. I can't fault the tool for its scrupulous honesty Commented May 28 at 4:04

5 Answers 5

4

You can use exiftool to removed all of the metadata and to output what is left, i.e. the image to standard out in binary format with the command:

exiftool filename.jpg  -all= -o - -b

And of course md5sum will except standard in as an input so you should be able to construct a pipe such as:

exiftool filename.jpg  -all= -o - -b | md5sum -
7
  • 2
    Note that the above does not change the file the file is read, metadata stripped and then the image data output into md5sum! You use sys::stdout rather than /temp/ Commented Jul 9, 2018 at 1:50
  • Oh wait, I didn’t read properly. If it uses sdtin then there will be no permanent damage Commented Jul 9, 2018 at 1:50
  • Come to think of it, when removing duplicate files I may end up removing the more desirable variant of the file. Maybe what really want is instead of deleting one of them, merging the exif data such that the md5sum output becomes identical Commented Jul 9, 2018 at 1:53
  • 1
    You only need to merge the EXIF data if the files are otherwise identical so your first step is to locate all of the duplicates (ignoring the EXIF data) then you can potentially use exiftool to extract all of the metadata from both files merge it and set one or both files to contain it - this will not be a one liner. Commented Jul 9, 2018 at 2:11
  • Yeah, a one liner is unrealistic after thinking this through more. It would be more of a shell script or groovy script if I want to do it reliably Commented Jul 9, 2018 at 2:38
4

For some reason exiftool did not work for me as it seemed to leave some metadata on, but replacing it with imagemagick convert worked great:

convert -strip filename.jpg -| md5sum
1

FWIW here is a quick one-liner to remove files where the image matches but the metadata does not:

find *_201* *_202[0-3] -type f -print | egrep -i "(jpg|arw|dng|tif|crw|cr3|nef|hif|heif|cs2|jpeg|png)" | while read file; do ofile="../$file"; if [ -f "$ofile" ]; then sha=`magick "$file" - 2>/dev/null | shasum`; osha=`magick "$ofile" - 2>/dev/null | shasum`; if [ "$sum" -eq "$osum" ]; then /bin/echo -n "-"; rm "$file"; else echo "$ofile differs - $osum vs $sum" >&2; fi; else echo "$ofile does not exist" >&2; fi; done 2> 20240527_exceptions.txt

I filtered out all the non-image c**p. Also I should not that the files I am removing are in a sub-folder. Each folder has the year appended and I don't want to delete anything from 2024. I write exceptions to a file called exceptions.txt and a string of "-" to stdout so I can see that it's doing stuff. There will be a short pause ...

I'm running this on a Mac under Sonoma so you may need to change a few details if you are a Linux person or other platform.

1

Here's how to generate a digest based only on pixel values using ImageMagick.

First, create some images, in various formats, i.e. BMP, GIF, PNG

magick -size 64x48 xc:red +write a.png +write a.gif a.bmp

Now get hex digests over just the pixels:

magick identify -format "%#:%f\n" a.*  
                      
dd2631e2587efb4fad5891366d906fa2cf3f554cc5c2f4da8ea0495c97b92909:a.bmp 
dd2631e2587efb4fad5891366d906fa2cf3f554cc5c2f4da8ea0495c97b92909:a.gif
dd2631e2587efb4fad5891366d906fa2cf3f554cc5c2f4da8ea0495c97b92909:a.png

You can check it ignores metadata such as the timestamp by creating two PNGs with different timestamps:

magick -size 64x48 xc:red a.png
sleep 2                             # to ensure a second has elapsed
magick -size 64x48 xc:red b.png

Now check the hashes still match despite different time:

identify -format "%#:%f\n" [ab].png

dd2631e2587efb4fad5891366d906fa2cf3f554cc5c2f4da8ea0495c97b92909:a.png
dd2631e2587efb4fad5891366d906fa2cf3f554cc5c2f4da8ea0495c97b92909:b.png

See what md5sum makes of them:

md5sum [ab].png
5d3c269e627b518c33148479018a1530  a.png
47717fe7262c465fca2a99b411f37c9f  b.png
1

There is also a Python project called jpegdupes (previously called imgdupes) that is specifically made to check .jpg files with identical image content, ignoring any changes in metadata (e.g. EXIF and other metadata).

It will check for image files and create a .signatures directory that will record the hashes for the image content. After it's done, it will display a list of the found duplicates as well as some options to delete them.

It is only specific to jpeg rather than all image types, though.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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