如何使用脚本检索照片的创建日期
How retrieve the creation date of photos with a script
我想做的是重新整理我的相机胶卷文件夹中的文件。使用创建日期,我想根据 Year/Month 使用创建日期的格式将它们放入文件夹中。
在这个回答中,他们解释了如何制作文件夹并组织它们:
#!/bin/bash
find $PHOTO_DIR -regextype posix-extended -type d -regex '.*/[0-9]{4}/[0-9]{2}/[0-9]{2}$' |
while read dir; do
newdir="$(echo $dir | sed 's@/\([0-9]\{4\}\)/\([0-9]\{2\}\)/\([0-9]\{2\}\)$@/--@')"
mv "$dir" "$newdir"
rmdir "$(dirname $dir)"
rmdir "$(dirname $(dirname $dir))"
done
但它没有说明如何获取创建日期,也许我应该从 EXIF 数据中获取元数据。怎么办?
我写了一个 bash 脚本来直接从我的 iphone/ipad 复制文件,并根据图像创建日期将它们复制到目标驱动器上的文件夹中。我使用在 http://www.sno.phy.queensu.ca/~phil/exiftool/
找到的名为 exiftool
的程序
对于给定的图像,我使用
将创建日期时间提取到一个数组中
DATEBITS=( $(exiftool -CreateDate -FileModifyDate -DateTimeOriginal "$IMGFILE" | awk -F: '{ print ":" ":" ":" ":" }' | sed 's/+[0-9]*//' | sort | grep -v 1970: | cut -d: -f1-6 | tr ':' ' ' | head -1) )
其中 $IMGFILE
是图像文件的路径。然后您可以使用
访问年、月、日等
YR=${DATEBITS[0]}
MTH=${DATEBITS[1]}
DAY=${DATEBITS[2]}
HR=${DATEBITS[3]}
MIN=${DATEBITS[4]}
SEC=${DATEBITS[5]}
创建用于存储图像文件的目录就很简单了
根据 exiftool 手册页'Renaming examples'
exiftool '-Directory<DateTimeOriginal' -d %Y/%m/%d "$dir"
如果只需要复制,还有一个选项:
exiftool -o . '-Directory<DateTimeOriginal' -d %Y/%m/%d "$dir"
除了文件被复制而不是移动之外,与上面的效果相同。
我一直在整理 1997 年以来的 14,000 张照片。这是一只熊,因为并非所有相机都是数码相机,尤其是早期的相机。我在图像文件中使用了 'CreateDate' 标签。
如果可能,我编写了以下 BASH 脚本来执行基于 EXIF 数据的排序。它首先查找 EXIF 'CreateDate' 标签。如果找到,它会使用它。如果不是,它会查找文件名的前 8 个字符以查看它们是否是有效日期(ANDROID,等等)。如果两者均未测试为阳性,它会查找 EXIF 'FileModifyDate' 标记,这可能不准确。如果找到 EXIF 'CreateDate',日期前缀 (YYYMMDD-) 将被添加到文件名中(如果它尚不存在),然后它将被移动到适当的目录中。如果所有三个测试都失败,则该文件将单独保留以供用户干预。
如果你运气好,相机支持,摄影师启用,日期可能会为你印在图像上。我不得不以这种方式对许多照片进行排序,因此请务必查看未处理的照片和使用 EXIF 'FileModifyDate' 排序方法的照片。
此外,如果您发现您有一些 KODAK PCD 图片文件,您可以像这样使用 ImageMajick 的“转换”:
convert $OrigFileName[$SUFX] -colorspace RGB "$(basename $OrigFileName .pcd).jpg"
然而,ImageMajick 并不总是将所有标签复制到新图像文件中,但您可以使用 EXIFTOOL 将标签传输到新图像文件中,如下所示:
exiftool -tagsFromFile $OrigFileName $(basename $OrigFileName .pcd).jpg
代码:
#! /bin/bash
# This script is used to sort photos. It uses the EXIFTOOL to
# 1st attempt to extract the photo's "CreateDate". If it is
# invalid, then the file name is checked to see if it begins
# with "YYYYMMDD", which is also checked for validity. If the
# prior two checks fail, then the photo's "FileModifyDate" is
# used but can be inaccurate.
# If a valid creation date is found and the file name is NOT
# date-encoded, then the file is renamed with a "YYYYMMDD-"
# prefix.
#=======================================================================
# Revision index:
# 2019-0704: KSV - Created and tested.
#=======================================================================
DEBUG=0 # Debugging
DRYRUN=0 # Do everything but move the files
NOTE="" # Notes
# ANSI COLORS
CRE="$(echo -e '\r3[K')"
RED="$(echo -e '3[1;31m')"
GRN="$(echo -e '3[1;32m')"
YEL="$(echo -e '3[1;33m')"
BLU="$(echo -e '3[1;34m')"
MAG="$(echo -e '3[1;35m')"
CYN="$(echo -e '3[1;36m')"
WHT="$(echo -e '3[1;37m')"
NML="$(echo -e '3[0;39m')"
#=======================================================================
# Functions
#=======================================================================
# Enter with: YEAR, MONTH and DAY
# Returns: 0=invalid date, 1=valid date
# EX: IsValidDate $YEAR $MONTH $DAY
IsValidDate() {
#echo "Parm: Y=,${#1} M=,${#2} D=,${#3}" >/dev/stderr
if ([ "" -ge "1950" ] && [ "" -le "2050" ]) || \
([ "" -ge "01" ] && [ "" -le "12" ]) || \
([ "" -ge "01" ] && [ "" -le "31" ]) ; then
echo "1" # valid date
else
echo "0" # invalid date
fi
}
# Dump debugging info
# EX: $(DumpDebug $FN $FILE $EXT $FN_WD $DATE $YEAR $MONTH $DAY "$NOTE")
DumpDebug() {
#echo "1=${#FN}, 2=${#FILE}, 3=${#EXT}, 4=${#FN_WD}, 5=${#DATE}, 6=${#YEAR}, 7=${#MONTH}, 8=${#DAY}, 9=${#NOTE}" >/dev/stderr
echo "================================"
echo "FN = "
echo "FILE = "
echo "EXT = "
echo "FN_WD = "
echo "DATE = "
echo "YEAR = "
echo "MONTH = "
echo "DAY = "
echo "ValidDate = $(IsValidDate )"
echo "NOTE = "
echo "================================"
}
#=======================================================================
# Script starts here
#=======================================================================
# Use exiftool to find video and photos
#exiftool -filename *.[JjGg][PpIi][GgFf] *.[Jj][Pp][Ee][Gg] *.[Mm][PpOo][Gg4Vv] 2>/dev/null | awk {'print '} | \
find . -maxdepth 1 -type f -iname "*.[JjGg][PpIi][GgFf]" -or \
-iname "*.[Jj][Pp][Ee][Gg]" -or \
-iname "*.[Mm][PpOo][Gg4Vv]" | \
while read FN ; do
FN=$(basename $FN) # strip the leading "./"
if [ -e $FN ] && [ ${#FN} != 0 ] ; then # be sure the file exists!
EXT=${FN##*.} # extract the extension
FILE=${FN%.*} # extract the base file name
# First attempt to see if there is a valid date prefix in the file name.
YEAR=$(echo ${FN:0:4} | egrep -E ^[0-9]+$ ) # insure digits only
MONTH=$(echo ${FN:4:2} | egrep -E ^[0-9]+$ ) # insure digits only
DAY=$(echo ${FN:6:2} | egrep -E ^[0-9]+$ ) # insure digits only
DATE="$YEAR:$MONTH:$DAY" # create a DATE string
# Check the filename's derived date from for validity (not NULL strings)
# and that the date falls within the proper range
if ([ ! -z "${YEAR}" ] && [ ! -z "${MONTH}" ] && [ ! -z "${DAY}" ]) && \
[ $(IsValidDate $YEAR $MONTH $DAY) == 1 ] ; then
if [ $DEBUG == 1 ] ; then echo "ValidDate: $(IsValidDate $YEAR $MONTH $DAY)" ; fi
FN_WD=0 # date prefix exists, do not append the derived date to the filename.
else
FN_WD=1 # append the derived date prefix to the filename.
fi
# Next, attempt to find an EXIF CreateDate from the file, if it exists.
DATE=$(exiftool -s -f -CreateDate $FN | awk '{print }')
# Perform sanity check on correctly extracted EXIF CreateDate
if [ "${DATE}" != "-" ] && [ "${DATE}" != "0000:00:00" ] ; then
# Good date extracted, so extract the year, month and day
# of month from the EXIF info
echo "A valid ${WHT}CreateDate${NML} was found, using it."
YEAR=${DATE:0:4}
MONTH=${DATE:5:2}
DAY=${DATE:8:2}
NOTE="(by CreateDate)"
else
# EXIF CreateDate invalid or not found, so attempt to derive the
# date from the file name.
YEAR=$(echo ${FN:0:4} | egrep -E ^[0-9]+$ ) # insure digits only
MONTH=$(echo ${FN:4:2} | egrep -E ^[0-9]+$ ) # insure digits only
DAY=$(echo ${FN:6:2} | egrep -E ^[0-9]+$ ) # insure digits only
DATE="$YEAR:$MONTH:$DAY" # create a DATE string
# check the extracted date from filename for validity (not NULL strings)
# and that the date falls within the proper range
#if [ -z "${YEAR}" ] || [ -z "${MONTH}" ] || [ -z "${DAY}" ] ; then
if ([ ! -z "${YEAR}" ] && [ ! -z "${MONTH}" ] && [ ! -z "${DAY}" ]) && \
[ $(IsValidDate $YEAR $MONTH $DAY) == 1 ] ; then
echo "A valid ${WHT}FileNameDate${NML} was found, using it."
NOTE="(by file name)"
else
# EXIF CreateDate and FileNameDate extraction failed, so attempt
# to extract the EXIF FileModifyDate from the file, if it exists.
DATE=$(exiftool -s -f -FileModifyDate $FN | awk '{print }')
# Perform sanity check on correctly extracted EXIF FileModifyDate
if [ "${DATE}" != "-" ] && [ "${DATE}" != "0000:00:00" ] ; then
# Good FileModifyDate found, extract the year, month and
# day of month from the EXIF info
echo "A valid EXIF CreateDate and FileNameDate were not found!"
echo " The innacurate ${WHT}FileModifyDate${NML} will be used."
YEAR=${DATE:0:4}
MONTH=${DATE:5:2}
DAY=${DATE:8:2}
NOTE="(!inaccurate! by FileModifyDate)"
FN_WD=0 # date prefix exists, do not append the derived date to the filename.
else
echo "Invalid date retrieved!"
if [ $DEBUG == 1 ] ; then
echo "Length = ${#YEAR}-${#MONTH}-${#DAY}"
fi
echo "Skipping File: $FN..."
echo
fi
fi
fi
# Modify the filename if a valid EXIF CreateDate or FileNameDate was found.
if [ $FN_WD == 0 ] ; then
FILE=${FILE}.${EXT}
else
FILE=${YEAR}${MONTH}${DAY}-${FILE}.${EXT}
fi
# Debug output
if [ $DEBUG == 1 ] ; then DumpDebug $FN $FILE $EXT $FN_WD $DATE $YEAR $MONTH $DAY "$NOTE" ; fi
# We have a date, hopefully a good one, move the file
if [ $DRYRUN == 0 ] ; then
# create the directory structure. Pipe errors to NULL
mkdir -p $YEAR/$MONTH/$DAY >/dev/null 2>&1
# move the file to the appropriate directory
echo " -> Moving $FN to $YEAR/$MONTH/$DAY/$FILE $NOTE"
mv $FN $YEAR/$MONTH/$DAY/$FILE
echo
else
echo "Dryrun: Moving $FN to $YEAR/$MONTH/$DAY/$FILE"
echo
fi
# Clear the variables
FN=""; FILE=""; EXT=""; FN_WD=""; DATE=""; YEAR=""; MONTH=""; DAY=""; NOTE=""
else
echo
echo "File $FN not found!"
echo
fi
done
一直在为相同或相似的问题苦思冥想。
Exiftool 是一个强大的东西,但是它有一些局限性,并不能真正解决文件重复问题。
这是我在脚本中使用的
# EXIFSubSecCreateDateParser extracts EXIF metadata: the year, month, day, hour, minute, second, subsecond,
# and generates date and note
EXIFSubSecCreateDateParser() {
# Define a variable and pass the arguments
EXIF_OUTPUT=""
# Substitute dots with a common colon delimiter
EXIF_OUTPUT_SUBSTITUTE="${EXIF_OUTPUT//./:}"
# Define delimiter
DELIMITER=":"
# Concatenate the delimiter with the main string
DELIMITED_EXIF_OUTPUT="${EXIF_OUTPUT_SUBSTITUTE}${DELIMITER}"
# Split the text based on the delimiter
EXIF_OUTPUT_ARRAY=()
while [[ "${DELIMITED_EXIF_OUTPUT}" ]]; do
EXIF_OUTPUT_ARRAY+=( "${DELIMITED_EXIF_OUTPUT%%${DELIMITER}*}" )
DELIMITED_EXIF_OUTPUT="${DELIMITED_EXIF_OUTPUT#*${DELIMITER}}"
done
# Assign the array values to the corresponding variables
YEAR="${EXIF_OUTPUT_ARRAY[0]}"
MONTH="${EXIF_OUTPUT_ARRAY[1]}"
DAY="${EXIF_OUTPUT_ARRAY[2]}"
HOUR="${EXIF_OUTPUT_ARRAY[3]}"
MINUTE="${EXIF_OUTPUT_ARRAY[4]}"
SECOND="${EXIF_OUTPUT_ARRAY[5]}"
SUBSECOND="${EXIF_OUTPUT_ARRAY[6]}"
DATE="${YEAR}:${MONTH}:${DAY}"
}
# Attempting to extract EXIF metadata from the file to an array.
EXIF_EXTRACT=( $(exiftool -s -f -SubSecCreateDate -CreateDate -Model "${WIPSortedFileAbsolutePath}" | awk '{print ":"}') )
# Assigning the array values to variables
EXIF_SubSecCreateDate_OUTPUT="${EXIF_EXTRACT[0]}"
EXIF_CreateDate_OUTPUT="${EXIF_EXTRACT[1]}"
EXIF_Model_OUTPUT="${EXIF_EXTRACT[2]}"
# Setting Target Directory structure with TargetDirectoryStructure
DestinationStructure="${YEAR}/${MONTH}/${DAY}"
# Setting Filename format
FormatedFileName="${MODEL}-${YEAR}${MONTH}${DAY}-${HOUR}${MINUTE}${SECOND}-${SUBSECOND}.${NormalisedFileExtension}"
# Moving the file to the Desination File Path
mv "${File}" "${DestinationPath}/${DestinationStructure}/${FormatedFileName}"
我找到了一些答案,但零碎的解决方案还不够。我最终以 .
为基础开始编写自己的东西
随便看看https://github.com/ivang-coder/Neatly-Sorted
它可能会为您的努力提供一些想法。
我想做的是重新整理我的相机胶卷文件夹中的文件。使用创建日期,我想根据 Year/Month 使用创建日期的格式将它们放入文件夹中。
在这个回答中,他们解释了如何制作文件夹并组织它们:
#!/bin/bash
find $PHOTO_DIR -regextype posix-extended -type d -regex '.*/[0-9]{4}/[0-9]{2}/[0-9]{2}$' |
while read dir; do
newdir="$(echo $dir | sed 's@/\([0-9]\{4\}\)/\([0-9]\{2\}\)/\([0-9]\{2\}\)$@/--@')"
mv "$dir" "$newdir"
rmdir "$(dirname $dir)"
rmdir "$(dirname $(dirname $dir))"
done
但它没有说明如何获取创建日期,也许我应该从 EXIF 数据中获取元数据。怎么办?
我写了一个 bash 脚本来直接从我的 iphone/ipad 复制文件,并根据图像创建日期将它们复制到目标驱动器上的文件夹中。我使用在 http://www.sno.phy.queensu.ca/~phil/exiftool/
找到的名为exiftool
的程序
对于给定的图像,我使用
将创建日期时间提取到一个数组中DATEBITS=( $(exiftool -CreateDate -FileModifyDate -DateTimeOriginal "$IMGFILE" | awk -F: '{ print ":" ":" ":" ":" }' | sed 's/+[0-9]*//' | sort | grep -v 1970: | cut -d: -f1-6 | tr ':' ' ' | head -1) )
其中 $IMGFILE
是图像文件的路径。然后您可以使用
YR=${DATEBITS[0]}
MTH=${DATEBITS[1]}
DAY=${DATEBITS[2]}
HR=${DATEBITS[3]}
MIN=${DATEBITS[4]}
SEC=${DATEBITS[5]}
创建用于存储图像文件的目录就很简单了
根据 exiftool 手册页'Renaming examples'
exiftool '-Directory<DateTimeOriginal' -d %Y/%m/%d "$dir"
如果只需要复制,还有一个选项:
exiftool -o . '-Directory<DateTimeOriginal' -d %Y/%m/%d "$dir"
除了文件被复制而不是移动之外,与上面的效果相同。
我一直在整理 1997 年以来的 14,000 张照片。这是一只熊,因为并非所有相机都是数码相机,尤其是早期的相机。我在图像文件中使用了 'CreateDate' 标签。
如果可能,我编写了以下 BASH 脚本来执行基于 EXIF 数据的排序。它首先查找 EXIF 'CreateDate' 标签。如果找到,它会使用它。如果不是,它会查找文件名的前 8 个字符以查看它们是否是有效日期(ANDROID,等等)。如果两者均未测试为阳性,它会查找 EXIF 'FileModifyDate' 标记,这可能不准确。如果找到 EXIF 'CreateDate',日期前缀 (YYYMMDD-) 将被添加到文件名中(如果它尚不存在),然后它将被移动到适当的目录中。如果所有三个测试都失败,则该文件将单独保留以供用户干预。
如果你运气好,相机支持,摄影师启用,日期可能会为你印在图像上。我不得不以这种方式对许多照片进行排序,因此请务必查看未处理的照片和使用 EXIF 'FileModifyDate' 排序方法的照片。
此外,如果您发现您有一些 KODAK PCD 图片文件,您可以像这样使用 ImageMajick 的“转换”:
convert $OrigFileName[$SUFX] -colorspace RGB "$(basename $OrigFileName .pcd).jpg"
然而,ImageMajick 并不总是将所有标签复制到新图像文件中,但您可以使用 EXIFTOOL 将标签传输到新图像文件中,如下所示:
exiftool -tagsFromFile $OrigFileName $(basename $OrigFileName .pcd).jpg
代码:
#! /bin/bash
# This script is used to sort photos. It uses the EXIFTOOL to
# 1st attempt to extract the photo's "CreateDate". If it is
# invalid, then the file name is checked to see if it begins
# with "YYYYMMDD", which is also checked for validity. If the
# prior two checks fail, then the photo's "FileModifyDate" is
# used but can be inaccurate.
# If a valid creation date is found and the file name is NOT
# date-encoded, then the file is renamed with a "YYYYMMDD-"
# prefix.
#=======================================================================
# Revision index:
# 2019-0704: KSV - Created and tested.
#=======================================================================
DEBUG=0 # Debugging
DRYRUN=0 # Do everything but move the files
NOTE="" # Notes
# ANSI COLORS
CRE="$(echo -e '\r3[K')"
RED="$(echo -e '3[1;31m')"
GRN="$(echo -e '3[1;32m')"
YEL="$(echo -e '3[1;33m')"
BLU="$(echo -e '3[1;34m')"
MAG="$(echo -e '3[1;35m')"
CYN="$(echo -e '3[1;36m')"
WHT="$(echo -e '3[1;37m')"
NML="$(echo -e '3[0;39m')"
#=======================================================================
# Functions
#=======================================================================
# Enter with: YEAR, MONTH and DAY
# Returns: 0=invalid date, 1=valid date
# EX: IsValidDate $YEAR $MONTH $DAY
IsValidDate() {
#echo "Parm: Y=,${#1} M=,${#2} D=,${#3}" >/dev/stderr
if ([ "" -ge "1950" ] && [ "" -le "2050" ]) || \
([ "" -ge "01" ] && [ "" -le "12" ]) || \
([ "" -ge "01" ] && [ "" -le "31" ]) ; then
echo "1" # valid date
else
echo "0" # invalid date
fi
}
# Dump debugging info
# EX: $(DumpDebug $FN $FILE $EXT $FN_WD $DATE $YEAR $MONTH $DAY "$NOTE")
DumpDebug() {
#echo "1=${#FN}, 2=${#FILE}, 3=${#EXT}, 4=${#FN_WD}, 5=${#DATE}, 6=${#YEAR}, 7=${#MONTH}, 8=${#DAY}, 9=${#NOTE}" >/dev/stderr
echo "================================"
echo "FN = "
echo "FILE = "
echo "EXT = "
echo "FN_WD = "
echo "DATE = "
echo "YEAR = "
echo "MONTH = "
echo "DAY = "
echo "ValidDate = $(IsValidDate )"
echo "NOTE = "
echo "================================"
}
#=======================================================================
# Script starts here
#=======================================================================
# Use exiftool to find video and photos
#exiftool -filename *.[JjGg][PpIi][GgFf] *.[Jj][Pp][Ee][Gg] *.[Mm][PpOo][Gg4Vv] 2>/dev/null | awk {'print '} | \
find . -maxdepth 1 -type f -iname "*.[JjGg][PpIi][GgFf]" -or \
-iname "*.[Jj][Pp][Ee][Gg]" -or \
-iname "*.[Mm][PpOo][Gg4Vv]" | \
while read FN ; do
FN=$(basename $FN) # strip the leading "./"
if [ -e $FN ] && [ ${#FN} != 0 ] ; then # be sure the file exists!
EXT=${FN##*.} # extract the extension
FILE=${FN%.*} # extract the base file name
# First attempt to see if there is a valid date prefix in the file name.
YEAR=$(echo ${FN:0:4} | egrep -E ^[0-9]+$ ) # insure digits only
MONTH=$(echo ${FN:4:2} | egrep -E ^[0-9]+$ ) # insure digits only
DAY=$(echo ${FN:6:2} | egrep -E ^[0-9]+$ ) # insure digits only
DATE="$YEAR:$MONTH:$DAY" # create a DATE string
# Check the filename's derived date from for validity (not NULL strings)
# and that the date falls within the proper range
if ([ ! -z "${YEAR}" ] && [ ! -z "${MONTH}" ] && [ ! -z "${DAY}" ]) && \
[ $(IsValidDate $YEAR $MONTH $DAY) == 1 ] ; then
if [ $DEBUG == 1 ] ; then echo "ValidDate: $(IsValidDate $YEAR $MONTH $DAY)" ; fi
FN_WD=0 # date prefix exists, do not append the derived date to the filename.
else
FN_WD=1 # append the derived date prefix to the filename.
fi
# Next, attempt to find an EXIF CreateDate from the file, if it exists.
DATE=$(exiftool -s -f -CreateDate $FN | awk '{print }')
# Perform sanity check on correctly extracted EXIF CreateDate
if [ "${DATE}" != "-" ] && [ "${DATE}" != "0000:00:00" ] ; then
# Good date extracted, so extract the year, month and day
# of month from the EXIF info
echo "A valid ${WHT}CreateDate${NML} was found, using it."
YEAR=${DATE:0:4}
MONTH=${DATE:5:2}
DAY=${DATE:8:2}
NOTE="(by CreateDate)"
else
# EXIF CreateDate invalid or not found, so attempt to derive the
# date from the file name.
YEAR=$(echo ${FN:0:4} | egrep -E ^[0-9]+$ ) # insure digits only
MONTH=$(echo ${FN:4:2} | egrep -E ^[0-9]+$ ) # insure digits only
DAY=$(echo ${FN:6:2} | egrep -E ^[0-9]+$ ) # insure digits only
DATE="$YEAR:$MONTH:$DAY" # create a DATE string
# check the extracted date from filename for validity (not NULL strings)
# and that the date falls within the proper range
#if [ -z "${YEAR}" ] || [ -z "${MONTH}" ] || [ -z "${DAY}" ] ; then
if ([ ! -z "${YEAR}" ] && [ ! -z "${MONTH}" ] && [ ! -z "${DAY}" ]) && \
[ $(IsValidDate $YEAR $MONTH $DAY) == 1 ] ; then
echo "A valid ${WHT}FileNameDate${NML} was found, using it."
NOTE="(by file name)"
else
# EXIF CreateDate and FileNameDate extraction failed, so attempt
# to extract the EXIF FileModifyDate from the file, if it exists.
DATE=$(exiftool -s -f -FileModifyDate $FN | awk '{print }')
# Perform sanity check on correctly extracted EXIF FileModifyDate
if [ "${DATE}" != "-" ] && [ "${DATE}" != "0000:00:00" ] ; then
# Good FileModifyDate found, extract the year, month and
# day of month from the EXIF info
echo "A valid EXIF CreateDate and FileNameDate were not found!"
echo " The innacurate ${WHT}FileModifyDate${NML} will be used."
YEAR=${DATE:0:4}
MONTH=${DATE:5:2}
DAY=${DATE:8:2}
NOTE="(!inaccurate! by FileModifyDate)"
FN_WD=0 # date prefix exists, do not append the derived date to the filename.
else
echo "Invalid date retrieved!"
if [ $DEBUG == 1 ] ; then
echo "Length = ${#YEAR}-${#MONTH}-${#DAY}"
fi
echo "Skipping File: $FN..."
echo
fi
fi
fi
# Modify the filename if a valid EXIF CreateDate or FileNameDate was found.
if [ $FN_WD == 0 ] ; then
FILE=${FILE}.${EXT}
else
FILE=${YEAR}${MONTH}${DAY}-${FILE}.${EXT}
fi
# Debug output
if [ $DEBUG == 1 ] ; then DumpDebug $FN $FILE $EXT $FN_WD $DATE $YEAR $MONTH $DAY "$NOTE" ; fi
# We have a date, hopefully a good one, move the file
if [ $DRYRUN == 0 ] ; then
# create the directory structure. Pipe errors to NULL
mkdir -p $YEAR/$MONTH/$DAY >/dev/null 2>&1
# move the file to the appropriate directory
echo " -> Moving $FN to $YEAR/$MONTH/$DAY/$FILE $NOTE"
mv $FN $YEAR/$MONTH/$DAY/$FILE
echo
else
echo "Dryrun: Moving $FN to $YEAR/$MONTH/$DAY/$FILE"
echo
fi
# Clear the variables
FN=""; FILE=""; EXT=""; FN_WD=""; DATE=""; YEAR=""; MONTH=""; DAY=""; NOTE=""
else
echo
echo "File $FN not found!"
echo
fi
done
一直在为相同或相似的问题苦思冥想。
Exiftool 是一个强大的东西,但是它有一些局限性,并不能真正解决文件重复问题。
这是我在脚本中使用的
# EXIFSubSecCreateDateParser extracts EXIF metadata: the year, month, day, hour, minute, second, subsecond,
# and generates date and note
EXIFSubSecCreateDateParser() {
# Define a variable and pass the arguments
EXIF_OUTPUT=""
# Substitute dots with a common colon delimiter
EXIF_OUTPUT_SUBSTITUTE="${EXIF_OUTPUT//./:}"
# Define delimiter
DELIMITER=":"
# Concatenate the delimiter with the main string
DELIMITED_EXIF_OUTPUT="${EXIF_OUTPUT_SUBSTITUTE}${DELIMITER}"
# Split the text based on the delimiter
EXIF_OUTPUT_ARRAY=()
while [[ "${DELIMITED_EXIF_OUTPUT}" ]]; do
EXIF_OUTPUT_ARRAY+=( "${DELIMITED_EXIF_OUTPUT%%${DELIMITER}*}" )
DELIMITED_EXIF_OUTPUT="${DELIMITED_EXIF_OUTPUT#*${DELIMITER}}"
done
# Assign the array values to the corresponding variables
YEAR="${EXIF_OUTPUT_ARRAY[0]}"
MONTH="${EXIF_OUTPUT_ARRAY[1]}"
DAY="${EXIF_OUTPUT_ARRAY[2]}"
HOUR="${EXIF_OUTPUT_ARRAY[3]}"
MINUTE="${EXIF_OUTPUT_ARRAY[4]}"
SECOND="${EXIF_OUTPUT_ARRAY[5]}"
SUBSECOND="${EXIF_OUTPUT_ARRAY[6]}"
DATE="${YEAR}:${MONTH}:${DAY}"
}
# Attempting to extract EXIF metadata from the file to an array.
EXIF_EXTRACT=( $(exiftool -s -f -SubSecCreateDate -CreateDate -Model "${WIPSortedFileAbsolutePath}" | awk '{print ":"}') )
# Assigning the array values to variables
EXIF_SubSecCreateDate_OUTPUT="${EXIF_EXTRACT[0]}"
EXIF_CreateDate_OUTPUT="${EXIF_EXTRACT[1]}"
EXIF_Model_OUTPUT="${EXIF_EXTRACT[2]}"
# Setting Target Directory structure with TargetDirectoryStructure
DestinationStructure="${YEAR}/${MONTH}/${DAY}"
# Setting Filename format
FormatedFileName="${MODEL}-${YEAR}${MONTH}${DAY}-${HOUR}${MINUTE}${SECOND}-${SUBSECOND}.${NormalisedFileExtension}"
# Moving the file to the Desination File Path
mv "${File}" "${DestinationPath}/${DestinationStructure}/${FormatedFileName}"
我找到了一些答案,但零碎的解决方案还不够。我最终以
随便看看https://github.com/ivang-coder/Neatly-Sorted
它可能会为您的努力提供一些想法。