使用 Syncthing API 监听 NFS 目录同步并自动转换 Nikon RAW 文件
在之前一篇 尼康Zf的Raw文件在immich以及MT Photos上的问题临时解决方案 中,我试着使用inotify来监控目录的变化,可惜忽略了目录是NFS挂载的,然后就没有成功监听到文件的变化。幸好syncthing有api可以使用,不过我理想中的方案是希望同步完成后推送通知,然后我执行获取jpg的脚本,可惜目前只能主动去调用api,监听目录的状态,于是修改了下脚本,其中需要额外安装jq,来解析json,API_KEY可以在操作-设置-常规下看到API密钥,目录ID的话在文件夹下可以看到文件夹ID,修改后的脚本如下:
#!/bin/bash
# 源目录和目标目录
SOURCE_DIR="/mnt/nfs_share/NikonRaw"
TARGET_BASE_DIR="/mnt/nfs_share/NikonJpg"
# 监听 URL 和配置
SYNC_URL="http://你的syncthing ip+端口/rest/events"
API_KEY="你的APIKEY"
SINCE_FILE="/root/syncthing_since.txt"
LOG_FILE="/root/listen_syncthing.log"
FOLDER_ID="你要监听的目录ID"
# 读取上次的 SINCE 值
if [ -f "$SINCE_FILE" ]; then
SINCE=$(cat "$SINCE_FILE")
else
SINCE=1055
fi
SYNCED_FILES=()
log() {
echo "$(date '+%Y-%m-%d %H:%M:%S') $1" | tee -a "$LOG_FILE"
}
debug_log() {
echo "[DEBUG] $(date '+%Y-%m-%d %H:%M:%S') $1" | tee -a "$LOG_FILE"
}
# 转换函数
convert_to_jpg() {
local input_file=$1
local relative_path="${input_file#$SOURCE_DIR/}"
local target_dir="${TARGET_BASE_DIR}/$(dirname "$relative_path")"
mkdir -p "$target_dir"
local output_file="${target_dir}/$(basename "${input_file%.NEF}.jpg")"
if [ -f "$output_file" ]; then
log "文件已转换,跳过:$output_file"
return
fi
if dcraw -e -c "$input_file" > "$output_file"; then
log "转换成功:$input_file -> $output_file"
exiftool -tagsFromFile "$input_file" -DateTimeOriginal -CreateDate -TimeZone -overwrite_original "$output_file"
log "EXIF 数据更新成功:$output_file"
else
log "转换失败:$input_file"
fi
}
# 监听同步事件
listen_sync_events() {
while true; do
log "监听同步事件 (since=$SINCE)..."
response=$(curl -s -H "X-API-Key: $API_KEY" "$SYNC_URL?since=$SINCE")
# 检查是否为空响应或格式错误
event_count=$(echo "$response" | jq 'length' 2>/dev/null)
if [[ -z "$event_count" || "$event_count" -eq 0 ]]; then
debug_log "响应为空或非预期格式,跳过处理。"
sleep 10
continue
fi
debug_log "Raw response: $response"
# 获取最新事件 ID
new_since=$(echo "$response" | jq -r '.[-1].id')
debug_log "Parsed new_since: $new_since"
if [[ "$new_since" =~ ^[0-9]+$ ]] && [ "$new_since" -gt "$SINCE" ]; then
echo "$new_since" > "$SINCE_FILE"
SINCE=$new_since
log "更新 since 为: $SINCE"
else
debug_log "new_since 无效或未更新: $new_since"
fi
# 处理事件
events=$(echo "$response" | jq -c ".[] | select(.data.folder == \"$FOLDER_ID\")")
debug_log "Filtered events: $events"
for event in $events; do
event_type=$(echo "$event" | jq -r '.type')
if [[ "$event_type" == "LocalIndexUpdated" ]]; then
filenames=$(echo "$event" | jq -r '.data.filenames[]')
for file in $filenames; do
full_path="$SOURCE_DIR/$file"
if [[ -f "$full_path" ]]; then
SYNCED_FILES+=("$full_path")
log "文件索引更新完成,加入转换队列: $full_path"
fi
done
fi
done
# 执行转换任务
if [ ${#SYNCED_FILES[@]} -gt 0 ]; then
for file in "${SYNCED_FILES[@]}"; do
convert_to_jpg "$file"
done
SYNCED_FILES=()
log "所有任务已完成,等待新的同步事件..."
sleep 5
else
log "没有新文件需要处理,延长等待时间..."
sleep 10
fi
done
}
listen_sync_events
评论
发表评论