Organize your pictures by EXIF tags with bash

Just a simple script to order your thousands of pictures by putting them in subdirectories on the basis of EXIF shot date:

#!/bin/bash
# BashButler 1.0 - 11/2007 by Eugenio Rustico
# Bash script to organize your pictures in folders by date
#
# GPL v3 license http://www.gnu.org/licenses/gpl-3.0.html

ls -1 *.jpg | while read fn
do
export dt=`exiv2 "$fn" | grep timestamp | awk '{ print $4 }' | tr ":" "-"`
if test ! -e ./$dt
then
mkdir $dt
fi
mv "$fn" ./$dt
echo File "$fn" moved in "$dt"
done

echo Good job!

I wrote it to setup 4.900 pictures which were all in the same directory, and it was really fast and useful. My unstoppable sense of humor conceived this amazing script name: Bash Butler. I'm very sorry for this. =)

Notes:
  • Of course you need exiv2 package on your system, but you can use other cli exif tools by modifying only one row;
  • With very little changes, you can modify the script to organize your pictures by different EXIF tags (e.g. different folders for different digital cameras);
  • Filenames with spaces are treated correctly;
  • By default mv does'nt overwrite destination files: so all remaining files in current directory are copies, and can be deleted.
GPL license v.3, of course.

9 comments:

Anonymous said...

Thanks, just what I was looking for... so simple.

Anonymous said...

Really many thanks. This is exactly what I was looking for.

Unknown said...

Here is an enhanced version: organize

Kaan said...

#!/bin/bash
# PictureRenamer 1.0 - 08/2009 by Kaan Atasever
# This script renames your pictures with date and time
#
# GPL v3 license http://www.gnu.org/licenses/gpl-3.0.html

ls -1 *.jpg | while read fn
do
export pa1=`exiv2 "$fn" | grep timestamp | awk '{ print $4 }' | tr ":" "-"`
export pa2=`exiv2 "$fn" | grep timestamp | awk '{ print $5 }' | tr ":" "-"`
export pa="$pa1 $pa2.jpg"
mv "$fn" "$pa"
echo File "$fn" renamed as "$pa"
done

echo All done!

Andy said...

Be careful if you have pics taken within same second - the script as it is now will overwrite all but the last one.

Anonymous said...

Can someone help me with this? The folders I want to run this on are on an external. How do I point the script to the external. Which parts specifically do I paste into Terminal? Thanks

Narcolessico said...

@Anonymous this scripts acts in the current directory, just CD to the directory where the drive is mounted (e.g. "cd /media/user/usbstick").

Anonymous said...

For anyone that come to this commen thread, here is an updated version that handles images that doesn't contain EXIF data

#!/bin/bash
# MediaRenamer 2.0 - Enhanced version
# This script renames image and video files based on their metadata creation date,
# and adds a "no_data_" prefix for files without metadata.
#
# GPL v3 license http://www.gnu.org/licenses/gpl-3.0.html

# List of supported file extensions for images and videos
media_extensions=("*.jpg" "*.jpeg" "*.png" "*.gif" "*.heic" "*.mp4" "*.3gp" "*.mov" "*.m4v" "*.mp")

# Loop through the specified file types
for ext in "${media_extensions[@]}"; do
for fn in $ext; do
# Skip if no files match the current extension
[ -e "$fn" ] || continue

# Extract creation date metadata using exiftool
creation_date=$(exiftool -CreateDate "$fn" | awk -F': ' '{print $2}')

if [ -n "$creation_date" ]; then
# If creation date is available, format it
formatted_date=$(echo "$creation_date" | sed 's/:/-/g' | awk '{print $1 " " $2}')
new_name="${formatted_date}.${fn##*.}"
mv "$fn" "$new_name"
echo "File \"$fn\" renamed as \"$new_name\""
else
# If no creation date, rename file with "no_data_" prefix
new_name="no_data_$fn"
mv "$fn" "$new_name"
echo "File \"$fn\" renamed as \"$new_name\""
fi
done
done

echo "All done!"

Narcolessico said...

An improvement after 17 years from the original post... I'm moved :'-) I appreciate it, man.

Post a Comment