使用 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

评论

此博客中的热门博文

飞牛私有云OS相册、MT Photos、immich简单对比

飞牛私有云OS使用AList挂载天翼云盘

飞牛私有云OS相册、MT Photos、immich简单对比(二)