246 lines
6.3 KiB
Bash
Executable File
246 lines
6.3 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
declare -A out_dirs=(
|
|
["image"]="${HOME}/media/photos"
|
|
["video"]="${HOME}/media/videos"
|
|
)
|
|
declare -a g_files=()
|
|
# list of sidecar extensions
|
|
SIDECAR="pp3 xmp pp2 bib"
|
|
# params
|
|
TITLE=
|
|
DELETE=0
|
|
DEBUG=0
|
|
YES=0
|
|
NO_JPEG=0
|
|
MONTH_ONLY=0
|
|
|
|
import_photo()
|
|
{
|
|
local title=$1
|
|
local image=$2
|
|
|
|
local mimetype
|
|
local mimetype_short
|
|
mimetype=$(exiftool -mimetype -s3 "${image}" 2>/dev/null)
|
|
mimetype_short=${mimetype%%/*}
|
|
|
|
# skip files not returning exif data
|
|
if [ x"$?" != "x0" ]
|
|
then
|
|
if [ ${DEBUG} -eq 1 ]
|
|
then
|
|
echo "Skip unknown file ${image}"
|
|
fi
|
|
return
|
|
fi
|
|
|
|
# skip unmanaged files
|
|
if [ "${mimetype_short}" != "image" -a "${mimetype_short}" != "video" ]
|
|
then
|
|
echo "Skip file ${image} of unmanaged mime type ${mimetype}"
|
|
return
|
|
fi
|
|
local out=${out_dirs[$mimetype_short]}
|
|
|
|
# handle raw+jpeg
|
|
if [ "${mimetype}" = "image/jpeg" -a ${NO_JPEG} -eq 1 ]
|
|
then
|
|
# if raw file exists, skip the jpeg
|
|
local file_count=${#g_files[@]}
|
|
local i
|
|
for (( i = 0; i < file_count ; i++ ))
|
|
do
|
|
if [ "${g_files[$i]}" != "${image}" -a "${g_files[$i]%.*}" = "${image%.*}" ]
|
|
then
|
|
if [ ${DELETE} -eq 1 ]
|
|
then
|
|
rm -f "${image}"
|
|
for side_ext in $SIDECAR
|
|
do
|
|
if [ -f "${image}.${side_ext}" ]
|
|
then
|
|
rm -f "${image}.${side_ext}"
|
|
fi
|
|
done
|
|
fi
|
|
echo "Skip file ${image} from a RAW+jpeg pair"
|
|
return
|
|
fi
|
|
done
|
|
fi
|
|
|
|
# prepend date prefix to dest file name
|
|
local file
|
|
local prefix
|
|
prefix=$((exiftool -q -d "%Y%m%d_%H%M%S" -if '($datetimeoriginal and ($datetimeoriginal ne "0000:00:00 00:00:00"))' -datetimeoriginal -s3 "${image}" 2>/dev/null ; \
|
|
exiftool -q -d "%Y%m%d_%H%M%S" -if '($createdate and ($createdate ne "0000:00:00 00:00:00"))' -createdate -s3 "${image}" 2>/dev/null ; \
|
|
exiftool -q -d "%Y%m%d_%H%M%S" -filemodifydate -s3 "${image}" 2>/dev/null) | head -n 1)
|
|
file=$(basename "${image,,}")
|
|
file="${prefix}_${file}"
|
|
|
|
# prepare dir name
|
|
local dir
|
|
local pattern
|
|
pattern="%Y/%Y-%m-%d"
|
|
if [ ${MONTH_ONLY} -eq 1 ]
|
|
then
|
|
pattern="%Y/%Y-%m"
|
|
fi
|
|
dir=$((exiftool -q -d "${pattern}" -if '($datetimeoriginal and ($datetimeoriginal ne "0000:00:00 00:00:00"))' -datetimeoriginal -s3 "${image}" 2>/dev/null ; \
|
|
exiftool -q -d "${pattern}" -if '($createdate and ($createdate ne "0000:00:00 00:00:00"))' -createdate -s3 "${image}" 2>/dev/null ; \
|
|
exiftool -q -d "${pattern}" -filemodifydate -s3 "${image}" 2>/dev/null) | head -n 1)
|
|
if [ "x${title}" != "x" ]
|
|
then
|
|
dir="${dir} - ${title}"
|
|
fi
|
|
|
|
# ensure out dir is created
|
|
if [ ! -d "${out}/${dir}" ]
|
|
then
|
|
mkdir -p "${out}/${dir}"
|
|
fi
|
|
|
|
if [ -f "${out}/${dir}/${file}" ]
|
|
then
|
|
echo "'${image}' =! '${out}/${dir}/${file}' already exists, aborting"
|
|
else
|
|
# copy file
|
|
echo "'${image}' => '${out}/${dir}/${file}'…"
|
|
cp -n --preserve=timestamps --no-preserve=mode "${image}" "${out}/${dir}/${file}"
|
|
if [ ${DELETE} -eq 1 ]
|
|
then
|
|
rm -f "${image}"
|
|
fi
|
|
# handle sidecar files if exists
|
|
for side_ext in $SIDECAR
|
|
do
|
|
if [ -f "${image}.${side_ext}" ]
|
|
then
|
|
echo "Copying sidecar ${side_ext} file ${image}.${side_ext}"
|
|
cp -n --preserve=timestamps --no-preserve=mode "${image}.${side_ext}" "${out}/${dir}/${file}.${side_ext}"
|
|
if [ ${DELETE} -eq 1 ]
|
|
then
|
|
rm -f "${image}.${side_ext}"
|
|
fi
|
|
fi
|
|
done
|
|
# Add the needed XMP metadata for later Digikam processing (the yellow flag, alias XMP-digiKam:PickLabel=2)
|
|
exiftool -xmp:XMP-digiKam:PickLabel=2 -overwrite_original -P "${out}/${dir}/${file}.xmp"
|
|
fi
|
|
}
|
|
|
|
|
|
while getopts "hdjmn:y" flag
|
|
do
|
|
case $flag in
|
|
h)
|
|
echo "Usage: $0 [options] <file|directory>..."
|
|
echo "-d : delete source"
|
|
echo "-j : RAW+jpeg, skip jpeg"
|
|
echo "-m : breakdown by month"
|
|
echo "-n <name> : title"
|
|
echo "-y : force-yes"
|
|
exit
|
|
;;
|
|
d)
|
|
DELETE=1
|
|
;;
|
|
j)
|
|
NO_JPEG=1
|
|
;;
|
|
m)
|
|
MONTH_ONLY=1
|
|
;;
|
|
n)
|
|
TITLE=${OPTARG}
|
|
case ${TITLE} in
|
|
*/*)
|
|
echo "'/' is forbidden in title"
|
|
exit 1
|
|
;;
|
|
esac
|
|
;;
|
|
y)
|
|
YES=1
|
|
;;
|
|
esac
|
|
done
|
|
shift "$((OPTIND-1))"
|
|
|
|
if [ "x${TITLE}" != "x" ]
|
|
then
|
|
echo "Processing queue with title: ${TITLE}"
|
|
else
|
|
echo "Processing queue with no title"
|
|
fi
|
|
if [ ${NO_JPEG} -eq 1 ]
|
|
then
|
|
echo "--- RAW+jpeg handling enabled ---"
|
|
fi
|
|
if [ ${DELETE} -eq 1 ]
|
|
then
|
|
echo "--- Deletion of source image enabled ---"
|
|
fi
|
|
if [ ${MONTH_ONLY} -eq 1 ]
|
|
then
|
|
echo "--- Image breakdown per month only ---"
|
|
fi
|
|
if [ ${YES} -ne 1 ]
|
|
then
|
|
read -p "Proceed? [Y/n] "
|
|
if [[ ! $REPLY =~ ^[Yy]*$ ]]
|
|
then
|
|
echo "Abort"
|
|
exit
|
|
fi
|
|
fi
|
|
|
|
# build a complete file list
|
|
add_file()
|
|
{
|
|
local file=$1
|
|
|
|
# skip sidecar files
|
|
for side_ext in $SIDECAR
|
|
do
|
|
if [[ "${file}" == *"${side_ext}" ]]
|
|
then
|
|
if [ ${DEBUG} -eq 1 ]
|
|
then
|
|
echo "Skip sidecar file"
|
|
fi
|
|
return
|
|
fi
|
|
done
|
|
|
|
g_files+=("${file}")
|
|
}
|
|
for rsrc in "$@"
|
|
do
|
|
if [ -f "${rsrc}" ]
|
|
then
|
|
add_file "${rsrc}"
|
|
elif [ -d "${rsrc}" ]
|
|
then
|
|
echo "Recursing into '${rsrc}'"
|
|
while read file
|
|
do
|
|
add_file ${file}
|
|
done < <(find "${rsrc}" -type f | sort)
|
|
fi
|
|
done
|
|
|
|
# now process the list
|
|
file_count=${#g_files[@]}
|
|
for (( i = 0; i < file_count ; i++ ))
|
|
do
|
|
if [ -f "${g_files[$i]}" ]
|
|
then
|
|
import_photo "${TITLE}" "${g_files[$i]}"
|
|
else
|
|
echo "warning : '${g_files[$i]}' does not exists. file vanished during import (typical for sidecar files with agressive globing or jpeg in RAW+jpeg mode)?"
|
|
fi
|
|
done
|
|
|