Add timestamp to image from Linux command line

13,988

If you want to write the date of the image file's creation into the image itself (if that's not what you want, please edit your question), you can use imagemagick.

  1. Install ImageMagick if not already installed:

    sudo apt-get install imagemagick
    
  2. Run a bash loop that will get the creation date of each photo and use convert from the imagemagick suite to edit the image:

    for img in *jpg; do convert "$img" -gravity SouthEast -pointsize 22 \
       -fill white -annotate +30+30  %[exif:DateTimeOriginal] "time_""$img"; 
    done
    

    For each image named foo.jpg, this will create a copy called time_foo.jpg with the time stamp on the bottom right. You can do this more elegantly, for multiple file types and nice output names but the syntax is a little more complex:

OK, that was the simple version. I wrote a script that can deal with more complex situations, files in sub directories, weird file name etc. As far as I know, only .png and .tif images can contain EXIF data so there is no point in running this on other formats. However, as a possible workaround you can use the file's creation date instead of the EIF data. This is very likely not the same as the date the image was taken though so the script below has the relevant section commented out. Remove the comments if you want it to process in this way.

Save this script as add_watermark.sh and run it in the directory that contains your files:

bash /path/to/add_watermark.sh

It uses exiv2 which you may need to install (sudo apt-get install exiv2). The script:

#!/usr/bin/env bash

## This command will find all image files, if you are using other
## extensions, you can add them: -o "*.foo"
find . -iname "*.jpg" -o -iname "*.jpeg" -o -iname "*.tif" -o \
 -iname "*.tiff" -o -iname "*.png" | 

## Go through the results, saving each as $img
while IFS= read -r img; do
    ## Find will return full paths, so an image in the current
    ## directory will be ./foo.jpg and the first dot screws up 
    ## bash's pattern matching. Use basename and dirname to extract
    ## the needed information.
    name=$(basename "$img")
    path=$(dirname "$img")
    ext="${name/#*./}"; 

    ## Check whether this file has exif data
    if exiv2 "$img" 2>&1 | grep timestamp >/dev/null 
    ## If it does, read it and add the water mark   
    then
    echo "Processing $img...";
    convert "$img" -gravity SouthEast  -pointsize 22 -fill white \
             -annotate +30+30  %[exif:DateTimeOriginal] \
             "$path"/"${name/%.*/.time.$ext}";
    ## If the image has no exif data, use the creation date of the
    ## file. CAREFUL: this is the date on which this particular file
    ## was created and it will often not be the same as the date the 
    ## photo was taken. This is probably not the desired behaviour so
    ## I have commented it out. To activate, just remove the # from
    ## the beginning of each line.

    # else
    #   date=$(stat "$img" | grep Modify | cut -d ' ' -f 2,3 | cut -d ':' -f1,2)
    #   convert "$img" -gravity SouthEast  -pointsize 22 -fill white \
    #          -annotate +30+30  "$date" \
    #          "$path"/"${name/%.*/.time.$ext}";
    fi 
done
Share:
13,988

Related videos on Youtube

Andrew
Author by

Andrew

Updated on September 18, 2022

Comments

  • Andrew
    Andrew over 1 year

    I have a folder full of images. I'm trying to add a timestamp onto the image itself, for every image, based on the date that the file was created. Is this possible? I've read this post here, but it uses exif data. My images do not have exif data.

    Can I directly add a timestamp using the date created? Or do I have to use exif data? If I have to use exif data, how would I write it using the date created?

    I'm using Ubuntu Server without GUI, so I'll need a command line solution. Can anyone help? Thanks!

  • Andrew
    Andrew over 10 years
    This is exactly what I'm looking for! However, I'm getting the following output: convert.im6: unknown image property "%[exif:DateTimeOriginal]" @ warning/property.c/InterpretImageProperties/3245. convert.im6: unable to open image `{img/%.*/.time.jpg}': No such file or directory @ error/blob.c/OpenBlob/2638. Also, I haven't decided if I want to use subdirectories yet; could you show how to use find as well? Thanks!
  • terdon
    terdon over 10 years
    @Andrew there are two possible issues, one is that I had not quoted the variables properly and so spaces in the file names would cause problems. Try the script in the updated answer. If it still fails your images probably do not contain the necessary EXIF data, I have included a (bad) workaround for that.
  • Andrew
    Andrew over 10 years
    It's been a while, but can you explain what "$path"/"${name/%.*/.time.$ext}" does? In particular, the /%.*/ part. Also, if I wanted to put the "time" part in front, e.g. time.a.jpg rather than a.time.jpg, how could I do it?
  • terdon
    terdon over 10 years
    @Andrew that's just string replacement, see here. It will replace everything after the last . character with .time.$ext ($ext is the extension captured earlier). To make it into time.a.jpg, change that to ${name/#/time.}.
  • Sven Greinert
    Sven Greinert almost 6 years
    -pointsize 48 or -pointsize 72 is certainly more legible. :-)