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:

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";

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
    Commented Aug 27, 2016 at 20:54
  • 1
    Use mv -i so that if collision does happen then you'll be prompted and can n the move. Commented Aug 27, 2016 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. Commented Aug 27, 2016 at 21:37

3 Answers 3


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

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

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


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.

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

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"
    mv "$base.jpg" "$base_$(($#+1)).jpg"
    mv -- "$f" "$base.jpg"

(Warning, untested code)


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


# 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";

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .