#!/bin/bash
# Authors : Nicolas Coevoet, Pierre-Yves Landuré
# this script read exifs informations of files and copy them to destination/YEAR/MONTH/yearmonthday_hourminutesecond.ext
# it also convert crw/.cr2 file to jpg
# no images will be remove or overwrite.
# You need to have :
# exiftool, exiv2 and ufraw 0.15 installed
#
CP="/bin/cp"
MKDIR="/bin/mkdir"
SED="/bin/sed"
BASENAME="/usr/bin/basename"
FIND="/usr/bin/find"
WC="/usr/bin/wc"
CUT="/usr/bin/cut"
TR="/usr/bin/tr"
EXIFTOOL="/usr/bin/exiftool"
MD5SUM="/usr/bin/md5sum"
UFRAW_BATCH="/usr/bin/ufraw-batch"

SCRIPT_NAME="${0}"

usage() {
  echo "

Usage :

  ${SCRIPT_NAME} [ --help ] [ --by-day ] [ --recursive ]
                 [ --raw-only ] [ --create-jpeg ]
                 [ --jpeg-folder jpeg-destination/ ]
                 source destination/

  This script help read exif informations of image files
  (CRW, CR2, NEF, JPEG and TIFF) in order to copy and sort
  the files to destination/YEAR/MONTH/yearmonthday_hourminutesecond.ext.
  It can also convert RAW files to JPEG.

  Available options are:

  -h
  --help
    Display this little help.

  -d
  --by-day
    By default, this script sort images in YEAR/MONTH folders. If this option
    is specified, the images are sorted in YEAR/MONTH/DAY folders.

  -r
  --recursive
    By default, this script process only images in the current folder.
    If recursive option is specified, it also search for images in sub-folders.

  -R
  --raw-only
    By default, this tool sort all files in the source folder. If this option is
    specified, it will only sort RAW files.
    Supported RAW files are CRW, CR2 and NEF.

  -j
  --create-jpeg
    If this option is specified, a jpeg version of RAW files is created.
    Supported RAW files are CRW, CR2 and NEF.

  -J jpeg-destination/
  --jpeg-folder jpeg-destination/
    By default, when the --create-jpeg option is specified, the jpeg files are
    created in the destination folder. If the jpeg folder is specified, the jpeg
    files are created in the specified jpeg-destination.

  source
    The source folder or image file.

  destination
    The destination folder where the images will be copied and sorted.
"
  exit 0
}

# We set default values
ONLY_RAW_FILES=0
CREATE_JPEG=0
BY_DAY=0
RECURSIVE=0
JPEG_FOLDER=""

SOURCE=""
DESTINATION_FOLDER=""

# Parse the command line 
while [ $# -ge 1 ]; do
  case "${1}" in
    -h|--help)
      usage
    ;;
   -d|--by-day)
      BY_DAY=1
    ;;
   -r|--recursive)
      RECURSIVE=1
    ;;
   -R|--raw-only)
      ONLY_RAW_FILES=1
    ;;
   -j|--create-jpeg)
      CREATE_JPEG=1
    ;;
   -J|--jpeg-folder)
      # in this case, $2 should be the conffile !
      if [ -n "${2}" ]; then
        JPEG_FOLDER="${2}"
      else
        echo "The --jpeg-folder option must be followed by a destination path."
        usage
      fi
      # we shift here to avoid processing the file path 
      shift
    ;;
    *)
      if [ -n "${SOURCE}" ]; then
        echo "Unknown option ${1}"
        usage
      fi

      SOURCE="${1}"
      DESTINATION_FOLDER="${2}"
      # we shift here to avoid processing the file path 
      shift
    ;;
  esac
  shift
done

if [ ! -n "${SOURCE}" ]; then
  usage
fi
if [ ! -n "${DESTINATION_FOLDER}" ]; then
  usage
fi

if [ ! -n "${JPEG_FOLDER}" ]; then
  JPEG_FOLDER="${DESTINATION_FOLDER}"
fi

FIND_OPTIONS=""

if [ ${RECURSIVE} -eq 0 ]; then
  FIND_OPTIONS="-maxdepth 0"
fi

${FIND} "${SOURCE}" ${FIND_OPTIONS} -type f | \
while read SOURCE_FILE; do
  # For each file in source folder.

  # We detect its extension, and fetch its exif date time information.
  SOURCE_EXTENSION=$(echo "${SOURCE_FILE##*.}" | ${TR} 'A-Z' 'a-z')
  SOURCE_BASENAME=$(${BASENAME} "${SOURCE_FILE}" ".${SOURCE_FILE##*.}")
  SOURCE_DATETIME=$(${EXIFTOOL} -DateTimeOriginal -fast -s -s -s -q "${SOURCE_FILE}" 2>/dev/null)
  DATETIME_COLON_COUNT=$(( $(echo "${SOURCE_DATETIME}" | ${SED} 's/[^:]//g' | ${WC} -m) - 1))
  SOURCE_MD5SUM=$(${MD5SUM} "${SOURCE_FILE}" | ${CUT} -d' ' -f1)

  if [ \( ${ONLY_RAW_FILES} -eq 0 \
    -a \( "${SOURCE_EXTENSION}" = "jpeg" \
    -o "${SOURCE_EXTENSION}" = "jpg" \
    -o "${SOURCE_EXTENSION}" = "tiff" \
    -o "${SOURCE_EXTENSION}" = "tif" \) \) \
    -o "${SOURCE_EXTENSION}" = "crw" \
    -o "${SOURCE_EXTENSION}" = "cr2" \
    -o "${SOURCE_EXTENSION}" = "nef" ]; then # Test if we process only raw files.

    # We try to find a appropriate destination filename.
    if [ $DATETIME_COLON_COUNT -eq 0 ]; then # Test if date detection failed.
      # We are not able to extract a date from file.
      TARGET_FOLDER="nodate"
      TARGET_FILE_BASE="${SOURCE_BASENAME}"
    else # Test if date detection failed.
      # We fetch date time components.
      DATE=$(echo "${SOURCE_DATETIME}" | ${CUT} -d' ' -f1)
      TIME=$(echo "${SOURCE_DATETIME}" | ${CUT} -d' ' -f2)

      YEAR=$(echo ${DATE} | ${CUT} -d':' -f1)
      MONTH=$(echo ${DATE} | ${CUT} -d':' -f2)
      DAY=$(echo ${DATE} | ${CUT} -d':' -f3)
      HOUR=$(echo ${TIME} | ${CUT} -d':' -f1)
      MINUTE=$(echo ${TIME} | ${CUT} -d':' -f2)
      SECOND=$(echo ${TIME} | ${CUT} -d':' -f3)

      TARGET_FOLDER="${YEAR}/${MONTH}"
      if [ ${BY_DAY} -ne 0 ]; then
        TARGET_FOLDER="${TARGET_FOLDER}/${DAY}"
      fi

      TARGET_FILE_BASE="${YEAR}${MONTH}${DAY}_${HOUR}${MINUTE}${SECOND}"
    fi # Test if date detection failed.

    TARGET_FILE="${TARGET_FILE_BASE}.${SOURCE_EXTENSION}"
    JPG_TARGET_FILE="${TARGET_FILE_BASE}.jpg"

    COUNT=0
    # If destination file already exist.
    while [ -s "${DESTINATION_FOLDER}/${TARGET_FOLDER}/${TARGET_FILE}" ];do
      DESTINATION_MD5SUM=$(${MD5SUM} "${DESTINATION_FOLDER}/${TARGET_FOLDER}/${TARGET_FILE}" | ${CUT} -d' ' -f1)

      # If destination file is same as source file, we do nothing.
      if [ "${SOURCE_MD5SUM}" = "${DESTINATION_MD5SUM}" ]; then
        break;
      fi

      TARGET_FILE="${TARGET_FILE_BASE}_${COUNT}.${SOURCE_EXTENSION}"
      JPG_TARGET_FILE="${TARGET_FILE_BASE}_${COUNT}.jpg"
      COUNT=$((${COUNT} + 1))
    done

    # We create destination folder if needed.
    ${MKDIR} --parent "${DESTINATION_FOLDER}/${TARGET_FOLDER}"
    ${MKDIR} --parent "${JPEG_FOLDER}/${TARGET_FOLDER}"

    TARGET="${DESTINATION_FOLDER}/${TARGET_FOLDER}/${TARGET_FILE}"
    JPG_TARGET="${JPEG_FOLDER}/${TARGET_FOLDER}/${JPG_TARGET_FILE}"
    if [ -s "${TARGET}" ]; then
      echo "  ${SOURCE_FILE} --> ${TARGET} Skipped"
    else
      # We copy the file.
      cp -a "${SOURCE_FILE}" "${TARGET}"
      echo "  ${SOURCE_FILE} --> ${TARGET}"
    fi

    if [ ${CREATE_JPEG} -ne 0 \
        -a ! -s "${JPG_TARGET}" \
        -a \( "${SOURCE_EXTENSION}" = "crw" \
        -o "${SOURCE_EXTENSION}" = "cr2" \
        -o "${SOURCE_EXTENSION}" = "nef" \) ]; then
      echo -n "    Converting to ${JPG_TARGET_FILE}..."
      ${UFRAW_BATCH} --overwrite --silent \
                --out-type=jpeg  --wb=camera  --base-curve=camera \
                 --curve=linear --interpolation=ahd --compression=90 \
                 --exif --output="${JPG_TARGET}" "${TARGET}"
      echo " Done"
    fi
  fi # Test if we process only raw files.
done


