- 上次整理照片:强大的 exiv2 助 Synology 照片整理一臂之力
- 由于
exiv2
不支持heic
图片和视频文件,联系Synology
推荐了exiftool
。
安装 exiftool
# 先安装 Perl 套件,然后开启 ssh-server
wget -o ~admin/www/Image-ExifTool-11.89.tar.gz https://exiftool.org/Image-ExifTool-11.89.tar.gz
tar -C ~admin/www -zxvf ~admin/www/Image-ExifTool-11.89.tar.gz
ln -s ~admin/www/Image-ExifTool-11.89/exiftool /usr/local/bin/exiftool
exiftool -ver
体验 exiftool
# 按照片拍摄年份,存入指定目录
exiftool '-Directory<CreateDate' -d "~/photo/%Y" ./*.{jpg,cr2,heic}
# 文件按格式改名
exiftool '-filename<CreateDate' -d "%Y/%Y%m%d-%H%M%S.%%le" ./*.{jpg,heic,cr2}
# 自带调试(只读打印)
exiftool '-testname<CreateDate' -d "%Y/%Y%m%d-%H%M%S.%%le" -r ~/photo
用后感 exiftool
exiftool 虽然强大,建议当工具使用。不少定制化的需求无法满足:
- 1、默认 -o 拷贝的时候,遇到没有源信息文件 会全堆在一块(异常图片处理不好)
- 2、不带文件重名覆盖的选项(遇到重复会改名,没有其它逻辑)
- 3、不支持目录排除(递归查找无法排除)
- 4、不输出改名后的信息,无法记录(输出信息少,嵌入脚本使用不友好)
- 5、改名/移动 功能不错,复制设计不足(宝贵的图片源稿不到最后不删、不动)
- 好在
exiftool
能补足exiv2
功能上的不足,一行命令就能修复未识别的文件:
find ~/Drive/Moments/Mobile ~/Drive/Backup/MobileDevice ! -path "*@eaDir*" -type f -iname "*.heic" -o -iname "*.cr2" -exec exiftool '-filename<CreateDate' -d "%Y%m%d-%H%M%S.%%le" {} \;
- 最终为了照片的数据安全,还是写脚本来整理照片吧
#/bin/bash
# while read -r fName; do touch "./${fName}"; done < Sample.txt
readonly debug=false # 调试开关
fList="${1:-/volume1/homes/higkoo/XiaoMi/Image/FileList.csv}"
dDir="${2:-/volume1/homes/higkoo/XiaoMi/Image/}" # 归档目录
readonly eLog="${dDir}Error.log"
declare -A sInfo=([c]="0:0" [t]="2000-11-22 11:22:33" [s]="/dev/zero" [d]="/dev/null") # 用于存行信息
declare -A dInfo=([Y]=2000 [m]=11 [d]=22 [H]=11 [M]=22 [S]=33 [p]="/dev/null") # 解析文件名信息
declare -r mCode=([0]="Noneed" [1]="Created" [2]="Exsit" [3]="Overwrite" [4]="Failed" [5]="Error" [6]="Unknow") # 错误码定义
declare -a dDirList=() # 减少文件操作,用内存操作替换
rCode=6 # 错误码
IFS=',' # 设定分隔符,read 行的同时完成解析
grep -nE '^0.*heic|^0.*HEIC' "${fList}" | while read -r sInfo[c] sInfo[t] sInfo[s] sInfo[d] ; do
unset lNum # 重置变量,避免异常时循环的数据污染
lNum="${sInfo[c]%:*}" # 此串在源文件所在的行号,方便 sed 使用
sCode="${sInfo[c]#*:}" # 此行第1列,错误码
sPath="${sInfo[s]}" # 文件源路径
dPath="${sInfo[d]}" # 文件新路径
sfName="${sPath##*/}" # 文件名(带后缀)
spName="${sfName%.*}" # 文件名(无后缀)
stStr="${spName#* }" # 时分秒串
sExt="${sfName##*.}" # 后缀名
if [ "${sfName:10:1}" = " " -a ${#spName} -eq 17 ]; then # 文件名时间串,视为可信
read dInfo[Y] dInfo[m] dInfo[d] dInfo[H] dInfo[M] dInfo[S] < <(date -d "${spName% *} ${stStr:0:2}:${stStr:2:2}:${stStr:4:2}" +"%Y,%m,%d,%H,%M,%S") 2>>"${eLog}"
dfName="${spName//-/}" && dfName="${dfName// /-}.${sExt,,}"
dInfo[p]="${dDir}${dInfo[Y]}/${dfName}"
nPath="${sPath%/*}/${dfName}" # 新文件名
else # 从文件 Meta 信息读拍摄时间,拼接目标文件全路径
dInfo[p]=`exiftool -d "${dDir}%Y/%Y%m%d-%H%M%S.${sExt,,}" -DateTimeOriginal -S -s "${sInfo[s]"` 2>>"${eLog}"
dInfo[Y]="${dInfo[p]:${#dDir}:4}"
nPath="${sPath%/*}/${dInfo[p]##*/}" # 新文件名
fi
mv -v "${sPath}" "${nPath}" 2>>"${eLog}" && sed -i "${lNum}s/${sPath##*/}/${dInfo[p]##*/}/" "${fList}" || rCode=4 # 更新日志
if [[ ! ${dDirList[*]} =~ (^|[[:space:]])"${dInfo[Y]}"($|[[:space:]]) ]]; then # 按需创建目录
mkdir -pv "${dDir}${dInfo[Y]}/" && dDirList+=("${dInfo[Y]}")
fi
if [[ ! -f "${dInfo[p]}" ]]; then # 拷贝到备份目录
cp -v "${nPath}" "${dInfo[p]}" 2>>"${eLog}" && rCode=1 || rCode=4
else
if [[ `stat --printf=%s "${dInfo[p]}"` -lt `stat --printf=%s "${nPath}"` ]]; then
cp -v "${nPath}" "${dInfo[p]}" 2>>"${eLog}" && rCode=3 || rCode=4
else
rCode=2 && echo -ne '-' # 文件存在且比源文件大,跳过
fi
fi
sed -i "${lNum}s/^${sCode},${sInfo[t]}/${rCode},`date +%F\ %T`/" "${fList}" 2>>"${eLog}" # 更新文件状态和时间
$debug && declare -p sInfo dInfo
sInfo=() # 用完清空
dInfo=() # 垃圾回收
exit 0
done
来源:oschina
链接:https://my.oschina.net/higkoo/blog/3186810