25

If I rename images via exiv to the exif date time, I do the following:

find . -iname \*jpg -exec exiv2 -v -t -r '%Y_%m_%d__%H_%M_%S' rename {} \;

Now it might happen that pictures have exactly the same timestamp (including seconds). How can I make the filename unique automatically?

The command should be stable in the sense that if I execute it on the same directory structure again (perhaps after adding new pictures), the pictures already renamed shouldn't change and if pictures with already existing filenames are added the new filenames should be unique as well.

My first attempt was just to leave the original basename in the resulting filename, but then the command wouldn't be stable in the sense above.

don_crissti
  • 79,330
  • 30
  • 216
  • 245
student
  • 17,875
  • 31
  • 103
  • 169

4 Answers4

35

You may want to try jhead instead which does that out-of-the-box (with a, b... z suffixes allowing up to 27 files with the same date) and doesn't have the stability issue mentioned by @meuh:

find . -iname '*jpg' -exec jhead -n%Y_%m_%d__%H_%M_%S {} +

Or using exiftool (example in man page):

exiftool -ext jpg '-FileName<CreateDate' -d %Y_%m_%d__%H_%M_%S%%-c.%%e .

(here with %-c being a numerical suffix starting with -)

Jeff Schaller
  • 66,199
  • 35
  • 114
  • 250
Stéphane Chazelas
  • 522,931
  • 91
  • 1,010
  • 1,501
7

My version of exiv2 (0.25 001900) will ask interactively what to do when the filename already exists.

exiv2: File `./2013_06_19__14_03_13.jpg' exists. [O]verwrite, [r]ename or [s]kip? 

By adding option -F it will instead automatically add an extra _1 (or _2 etc) to the name.

Renaming file to ./2013_06_19__14_01_53_1.jpg, updating timestamp

If the command is run a second time it says:

This file already has the correct name

and does nothing, but it gets confused if there is the _1 part, and will rename it _2. It will toggle like this in a non-destructive way on each run. You can ignore this if you like, or change your find pattern to ignore files matching the date pattern with an _ part.

For example, the regex pattern for the date format begins [0-9]{4}_[0-9]{2}_.... To simplify, I'll just look for a mix of 20 characters from the set 0..9 and _, which is regex [0-9_]{20}. To this the suffix of _ followed by at least 1 digit to look for is _[0-9]{1,}.jpg. Since the regex has to match the whole path, and not just the basename, the final regex including the directory is .*/[0-9_]{20}_[0-9]{1,}.jpg.

So you can use a find like:

find . -regextype posix-extended ! -iregex '.*/[0-9_]{20}_[0-9]{1,}.jpg' -iname '*.jpg' ...
meuh
  • 49,672
  • 2
  • 52
  • 114
6

Exiv2 can handle it on its own. I also spent a lot of time looking for help on this, until I went to see the exiv2 manual. The -F option solves this problem.

exiv2 -r'%Y_%m_%d__%H_%M_%S' -F *.jpg

It will append a _N at the end if the file already exist.

And for thoses who are looking for an option that allow create folder.

exiftool -r '-FileName<DateTimeOriginal' -d %Y/%m/%d/%%f%%-c.%%e *
J.Adler
  • 276
  • 2
  • 6
0

The pyrenamer will not work on my new installed Ubuntu 16.04, therefore I have to find another way to solve this problem too.

I have files such as IMG_0001.JPG, IMG_0002.JPG,... in one folder. Check this site, https://stackoverflow.com/questions/917260/can-var-parameter-expansion-expressions-be-nested-in-bash

Install the "exiv2" first, and I wrote the following command line:

for img in $(ls *.[Jj][Pp][Gg] 2> /dev/null); do exiv2 -r'%Y%m%d_%H%M%S_'"$(tmp=${img%%.*};echo ${tmp##*_})" rename "$img" ; done

The output filenames are YYYYMMDD_HHMMSS_0001.JPG, YYYYMMDD_HHMMSS_0002.JPG,... etc. Even the photos were taken at the same second, the original photo serial number will make the difference.

chuck lee
  • 1
  • 1