#!/bin/bash #=============================================================# # Image Sorting Script: Kevin Muma - http://kevinmuma.com # #-------------------------------------------------------------# # Usage: # # ./sort_imgs.sh source_dir destination_dir # # # # This script recursively copies all images under the # # source_dir to a subdirectory in destination_dir based on # # the file's date. # # # # Relevant data for each image is also copied from # # Picases.ini files (if they exist) to the new directories. # # # # Notes: # # - This script was tested on Windows running under Cygwin it # # may not work correctly under Linux/Unix. # # # # - jhead is used to # # get the date information from jpeg headers # # # #=============================================================# fileTypes="jpg,jpeg,png,gif,psd,bmp,crw,thm,tif,tiff" # handle windows paths under cygwin if [[ "$TERM" == "cygwin" ]]; then source="`cygpath "$1"`" dest="`cygpath "$2"`" else source="$1" dest="$2" fi #makes the directory including needed subdirs # $1 - Base Directory # $2 - The Sub Directories to make make_dir() { curDir="$1"; OLDIFS=$IFS #save IFS IFS=/ for dirToAdd in $2 do curDir="$curDir/$dirToAdd" #if dir doesn't exist if [ ! -e "$curDir" ]; then # make it mkdir "$curDir" fi done IFS=$OLDIFS #reset IFS } #make regex to find files with extensions in $fileTypes fileTypes=".*\.\(${fileTypes//,/\|}\)" # loop through all the image files find "$source" -iregex "$fileTypes" -print0 | \ while read -d "" photo do echo "$photo" # get photo info if [[ "$TERM" == "cygwin" ]]; then jhead_photo="`cygpath -d "$photo"`" else jhead_photo="$photo" fi header=`jhead "$jhead_photo"` if [ -z "$header" ]; then echo "Error running jhead on $photo" >&2 fi # extract date and time dateTime=`echo "$header" | grep "Date/Time"` if [ -z "$dateTime" ] || \ [[ "$dateTime" == \ "Date/Time : 0000:00:00 00:00:00" ]]; then dateTime=`echo "$header" | grep "File date"` fi if [ -z "$dateTime" ]; then # get modified date from file in same format jhead uses dateTime=$(date -d"`stat -c%y "$photo"`" \ +"%Y:%m:%d %H:%M:%S") if [ -z "$dateTime" ]; then echo "Error can't get date for $photo" >&2 #just copy the file make_dir "$dest" "unknown_date" cp -p "$photo" \ "$dest/unknown_date/`basename "$photo"`" continue #goto next file fi fi # format the date right dateTime=${dateTime#*: } # remove "Date/Time : " dateTime=${dateTime/:/-} # replace first 2 : with - dateTime=${dateTime/:/-} echo "$dateTime" fileName=`basename "$photo"` # edit this line to change the output file name/dir destName=`date -d"$dateTime" \ "+%Y/%m.%b %d/%H.%M.%S_$fileName"` # check to see if the file exists if [ -e "$dest/$destName" ]; then # only copy if the new image is bigger # this should make sure thumbnail images do not overwrite # the original full size image if (( `stat -c%s "$photo"` <= \ `stat -c%s "$dest/$destName"` )); then echo "File exists not copying image $photo" >&2 continue #do not copy this image fi fi newSubdir=`dirname "$destName"` if [ ! -e "$newSubdir" ]; then make_dir "$dest" "$newSubdir" fi # copy the image file cp -p "$photo" "$dest/$destName" # copy Picasa.ini entries srcDir=`dirname "$photo"` if [ -e "$srcDir/Picasa.ini" ]; then srcFileName=`basename "$photo"` destDir=`dirname "$dest/$destName"` destFileName=`basename "$dest/$destName"` # setup new Picasa.ini if [ ! -e "$destDir/Picasa.ini" ]; then echo -e -n '[encoding]\x0D\x0Autf8=1\x0D\x0A' \ > "$destDir/Picasa.ini" fi # read picasa.ini add [ to start for gawk echo "\[" | cat - "$srcDir/Picasa.ini" | \ # separate on [ and print first entry with $srcFileName gawk 'BEGIN {RS="[";m=0} /'"$srcFileName"'/ {m++; if(m==1) print}' | \ # replace old name with the new file name sed "s/$srcFileName\]/\[$destFileName\]/" | \ # remove blank lines and convert to CRLF grep '.' | u2d -D >> "$destDir/Picasa.ini" fi echo "$destName" echo "--" done