5

I want to rename a bunch of pictures from past holidays, taken by different people using different devices (mobile, camera, etc.) and from different angles. I just wrote a little bash script to help me:

#!/bin/bash
for f in *; do
  # generate random id to prevent deletion of files with duplicate names 
  randomid=$(tr -dc "[:alnum:]" < /dev/urandom | head -c 10)
  # add modification date and time including seconds to the filename, attach location and random id 
  mv -- "$f" "$(date +%Y-%m-%d-%R:%S -r "${f}")_location_${randomid}.jpg";
done

The results are files with names which look like that: 2016-08-09-15:56:24_location_uPe38A20tn.jpg

I had to add the random id, as there are pictures, taken on the same DATETIME and second, so files ended up having duplicate file names and were deleted in the process.

Do you see another way of making sure pictures, which were taken on the same date in the same second, will not be deleted - other than my idea with the random id?

Thanks for your help!

  • Why don't you use the author's or device's name instead of a random id? – choroba Aug 27 '16 at 20:54
  • 1
    Use mv -i so that if collision does happen then you'll be prompted and can n the move. – Stephen Harris Aug 27 '16 at 21:20
  • 1
    You can try and see if exiftool gives you the metadata for the images. As the devices are different, the "Camera Model Name" field could be different which you could use. In case of same device type (two phones going off simultaneously), you could resort to a random number - however u may be able to identify certain features that will allow you to distinguish devices - I do not know - but running the exiftool on a bunch of different photos can help you. – SACHIN GARG Aug 27 '16 at 21:37
2

This will give duplicates numbers 1, 2, 3, and so on.

dest=$(date +%Y-%m-%d-%R:%S -r "${f}")_location_
id=
while [ -f "$dest""$id".jpg ] ; do
    ((id++))
done
dest="$dest""$id".jpg
mv -- "$f" "$dest"

It should be put inside the for f in * loop.

2

I don't see any good reason for random distinguishers here. If you have no natural name to distinguish the files, use a counter, it looks friendlier. The simple solution is to use a systematic, global counter.

counter=1
for f in *; do
  base="$(date +%Y-%m-%d-%R:%S -r "${f}")_location_"
  mv -- "$f" "$base_$counter.jpg"
  counter=$((counter+1))
done

If you want to use a counter only when there are clashes, test the file names before renaming.

for f in *; do
  base="$(date +%Y-%m-%d-%R:%S -r "${f}")_location_"
  set -- "$base"*.jpg
  if [ -e "$1" ]; then
    if [ "$1" = "$base.jpg" ]; then
      mv "$base.jpg" "$base_1.jpg"
    fi
    mv "$base.jpg" "$base_$(($#+1)).jpg"
  else
    mv -- "$f" "$base.jpg"
  fi
done

(Warning, untested code)

1

Here are some minor improvements to your script. It prompts on possible duplicates and considers the filename extension:

#!/bin/bash

# for each file
for f in *.{jpg,jpeg}; do
  # generate random id to prevent deletion of duplicates
  randomid=$(tr -dc "[:alnum:]" < /dev/urandom | head -c 10)
  # add modification date and time (divided by dashes) to the current filename
  # -i prompts on possible duplicates. 
  mv -i -- "$f" "$(date +%Y-%m-%d-%R:%S -r "${f}")_location_${randomid}.jpg";
done

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.