Last active
April 6, 2024 09:47
pho.sh
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
## 运行本脚本需要事先安装好以下包:bc exiftool ffmpeg findutils grep jq mediainfo perl | |
## 对于三种途径都获取不到时间的话,会将这类文件路径写入源文件夹下的 "不能处理的文件清单.txt" | |
## 仅处理源文件夹下的mp4和jpg格式的文件,将其复制到Pho下面能识别的目录结构,源文件夹下的文件不会被删除。 | |
## 源文件夹,绝对路径 | |
source_dir="" | |
## 目标文件夹,绝对路径 | |
target_dir="" | |
## 缩略图文件夹,默认在目标文件夹下面,即使要在其他地方生成,也要自己软连接到目标文件夹下,并且能够在webdav中正常识别 | |
thumbnail_dir="$target_dir/.thumbnail" | |
## 依次按照什么顺序获取照片/视频的拍摄时间,如果从第一项获取不到就尝试获取第二项,如果第二项仍然获取不到再获取第三项。可以调整这三项的顺序。 | |
## 一般来说,file_modify_time 是肯定会存在的,而其他两项不一定会存在,所以建议将 file_modify_time 作为最后的兜底。 | |
## exif_time:是exif信息中的拍摄日期,可以在Windows中照片上鼠标 右键->属性->详细信息 中查看到 | |
## filename_time:是照片/视频文件名中的时间信息,只要含有年月日时分秒信息即可 | |
## file_modify_time:照片/视频文件的修改日期,可以在Windows中照片上鼠标 右键->属性->详细信息 中查看到 | |
method_to_get_time=( exif_time filename_time file_modify_time ) | |
######################## 分隔线 ######################## | |
## $1: 文件完整路径 | |
exif_time() { | |
local file="$1" | |
local exiftime=$(exiftool "$file" | grep -P '^Create Date' | awk '{print $4$5}' | perl -pe "s|:||g" | head -1 | cut -c1-14) | |
if [[ -n $exiftime && ${#exiftime} == 14 && $exiftime != 00000000000000 ]]; then | |
echo "$exiftime" | |
fi | |
} | |
## $1:文件完整路径 | |
filename_time() { | |
local file="$1" | |
local basename=$(basename "$file") | |
local filenametime=$(echo "$basename" | grep -oP "20[0-2]\d(_|-|\.)?(0[1-9]|1[0-2])(_|-|\.)?(0[1-9]|[12]\d|3[01])(_|-|\.)?([01]\d|2[0-3])(_|-|\.)?[0-5]\d(_|-|\.)?[0-5]\d" | perl -pe '{s|_||g; s|-||g; s|\.||g}') | |
if [[ -n $filenametime && ${#filenametime} == 14 ]]; then | |
echo "$filenametime" | |
fi | |
} | |
## $1: 文件完整路径 | |
file_modify_time() { | |
local file="$1" | |
local filemodifytime=$(date +'%Y%m%d%H%M%S' -d @$(stat -c "%Y" "$file")) | |
if [[ -n $filemodifytime && ${#filemodifytime} == 14 ]]; then | |
echo "$filemodifytime" | |
fi | |
} | |
if [[ -f "$source_dir/不能处理的文件清单.txt" ]]; then | |
rm -rf "$source_dir/不能处理的文件清单.txt" | |
fi | |
find "$source_dir" -type f \( -iname "*.jpg" -o -iname "*.mp4" \) | sort | while read file; do | |
targettime="" | |
basename=$(basename "$file") | |
dirname=$(dirname "$file") | |
## 获取时间 | |
for ((i=0; i<${#method_to_get_time[@]}; i++)); do | |
targettime=$(${method_to_get_time[i]} "$file") | |
if [[ -n "$targettime" ]]; then | |
break | |
fi | |
done | |
if [[ -n $targettime ]]; then | |
## 获取年、月、日、时、分、秒 | |
year=$(echo "$targettime" | cut -c1-4) | |
month=$(echo "$targettime" | cut -c5-6) | |
day=$(echo "$targettime" | cut -c7-8) | |
hour=$(echo "$targettime" | cut -c9-10) | |
minute=$(echo "$targettime" | cut -c11-12) | |
second=$(echo "$targettime" | cut -c13-14) | |
## 创建对应的文件夹 | |
dirname_new="${target_dir}/${year}/${month}/${day}" | |
dirname_new_thumbnail="${thumbnail_dir}/${year}/${month}/${day}" | |
if [[ ! -d "$dirname_new" ]]; then | |
mkdir -p "$dirname_new" | |
fi | |
if [[ ! -d "$dirname_new_thumbnail" ]]; then | |
mkdir -p "$dirname_new_thumbnail" | |
fi | |
## 复制文件 | |
# touch -d "${year}-${month}-${day}T${hour}:${minute}:${second}" "$file" # 这一句可以按照“拍摄时间”(或者文件名中的时间)重设文件的“修改时间”,如有需要,可解除注释 | |
cp -afv "$file" "${dirname_new}/${basename}" | |
## 生成缩略图 | |
case $file in | |
*.jpg | *.JPG) minpx=200;; | |
*.mp4 | *.MP4) minpx=800;; | |
esac | |
info=$(mediainfo --Output=JSON "$file" | jq .media.track[]) | |
width=$(echo $info | jq -r .Width | grep -v null | head -1) | |
height=$(echo $info | jq -r .Height | grep -v null | head -1) | |
if [[ $width -gt $height ]]; then | |
width_n=$(printf "%.0f\n" $(echo "scale=2; $width * $minpx / $height" | bc)) | |
height_n=$minpx | |
if [[ $height_n -ge $height ]]; then | |
height_n=$height | |
width_n=$width | |
fi | |
else | |
width_n=$minpx | |
height_n=$(printf "%.0f\n" $(echo "scale=2; $height * $minpx / $width" | bc)) | |
if [[ $width_n -ge $width ]]; then | |
height_n=$height | |
width_n=$width | |
fi | |
fi | |
echo "生成缩略图: $dirname_new_thumbnail/${basename}" | |
case $file in | |
*.jpg | *.JPG) | |
ffmpeg -loglevel quiet -hide_banner -nostdin -stats -y -i "$file" -vf scale=${width_n}x${height_n} "$dirname_new_thumbnail/${basename}" | |
;; | |
*.mp4 | *.MP4) | |
ffmpeg -loglevel quiet -hide_banner -nostdin -stats -y -i "$file" -vf "select=eq(n\,0)" -vframes 1 /tmp/tmp_pho.jpg | |
ffmpeg -loglevel quiet -hide_banner -nostdin -stats -y -i "/tmp/tmp_pho.jpg" -vf scale=${width_n}x${height_n} "$dirname_new_thumbnail/${basename%.*}.jpg" | |
mv "$dirname_new_thumbnail/${basename%.*}.jpg" "$dirname_new_thumbnail/${basename}" | |
;; | |
esac | |
echo | |
## 如果三种途径都获取不到时间,则记录下来 | |
else | |
echo -e "无法获取到时间:$file\n" | |
echo "$file" >> "$source_dir/不能处理的文件清单.txt" | |
fi | |
done |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment