menu
  • watchman 实践
  • Calibre 能否添加相同 isbn 的图书。
  • Watchman 针对不 同目录不同脚本,把原先目录的信息加入书的元数据
  • systemd.path ?
  • inotifywait !

calibre 没有 headless 版本还是挺困扰的。

calibre 通过原始文件反查 id 太麻烦,也就是说删除文件和文件变更都不太好实现,而重复添加文件会报错。

所以只要通过 inotifywait 监听 CLOSE_WRITE 和 MOVE_TO ,就足够了。

inotifywait manpage 居然没有 include 参数,一直以为不支持。实际上 –help 是有支持 include 的

通过文件反查 id

ebook-meta {} | sed -n -e "s/Identifiers\s*:\s*\(.*\)/\1/p"

calibre 用的是 sqlite 的数据库,很多需求应该可以自己查库解决

过滤处 calibre 支持的格式,手动移除了 HTML

grep -E -i -x  ".*\.((AZW)|(AZW3)|(AZW4)|(CBZ)|(CBR)|(CBC)|(CHM)|(DJVU)|(DOCX)|(EPUB)|(FB2)|(FBZ)|(HTMLZ)|(LIT)|(LRF)|(MOBI)|(ODT)|(PDF)|(PRC)|(PDB)|(PML)|(RB)|(RTF)|(SNB)|(TCR)|(TXT)|(TXTZ))"

通过 xargs 让上个命令的每行输出,执行一个命令

xargs -L 1 -d '\n' -I {}

将路径转换为数组(zsh 下报错:read: bad option: -a)

IFS='/' read -ra  array <<< "/mnt/s3/books/rslsync/电子书资源共享(英文)/Travel(旅行)/The Art of Travel(旅行的艺术).mobi"

获取ebook identifiers:

find /mnt/s3/books/rslsync | grep -E -i -x  ".*\.((AZW)|(AZW3)|(AZW4)|(CBZ)|(CBR)|(CBC)|(CHM)|(DJVU)|(DOCX)|(EPUB)|(FB2)|(FBZ)|(HTMLZ)|(LIT)|(LRF)|(MOBI)|(ODT)|(PDF)|(PRC)|(PDB)|(PML)|(RB)|(RTF)|(SNB)|(TCR)|(TXT)|(TXTZ))"  | tail -n 10  | xargs -L 1 -d '\n' -I {} ebook-meta {} | sed -n -e "s/Identifiers\s*:\s*\(.*\)/\1/p" | xargs -L 1 -d '\n' -I {} calibredb --library-path '/mnt/s3/MainCalibre' search identifiers:"{}"

最终脚本 calibre_helper.sh

#! /bin/bash -x

# set if empty
if [[ -z $CALIBRE_LIBRARY_PATH ]]
then
    CALIBRE_LIBRARY_PATH='/mnt/s3/books/calibre'
fi

if [[ -z $CALIBRE_PATTERN ]]
then
    CALIBRE_PATTERN=".*\.((AZW)|(AZW3)|(AZW4)|(CBZ)|(CBR)|(CBC)|(CHM)|(DJVU)|(DOCX)|(EPUB)|(FB2)|(FBZ)|(HTMLZ)|(LIT)|(LRF)|(MOBI)|(ODT)|(PDF)|(PRC)|(PDB)|(PML)|(RB)|(RTF)|(SNB)|(TCR)|(TXT)|(TXTZ))"
fi

if [[ -z $WATCH_PATH ]]
then
    WATCH_PATH='/mnt/s3/books/calibre'
fi

function add_to_calibre()
{
    file=$1
    IFS='/'
    read -ra array <<< $file
    IFS=' '
    len=`expr ${#array[@]} - 7`
    tags=`echo ${array[@]:5:${len}} | sed -n 's/\s/,/gp'`
    echo ${array[-1]} ${tags}
    calibredb --library-path ${CALIBRE_LIBRARY_PATH} add -T "${tags}" "${file}"
}


function process_find(){
    while read -r input; do
        add_to_calibre "$input"
    done
}

# inotifywait 的 close_write moved_to 事件
function process_inotify(){
    while read -r log; do
        echo $log # 打印日志
        # 日志格式 [06/07/20 23:57 CLOSE_WRITE,CLOSE] /tmp/test/atc abs.pdf
        file=`sed -n 's/\[.*\]\s//p' <<< $log`
        if grep -E -i -x  "$CALIBRE_PATTERN" <<< $file > /dev/null
        then
            # 目标文件
            echo add_to_calibre $file
        #else
           # ignore
        fi
        done
}

# 首次运行将监听目录的当前所有电子书添加到 calibre
function init_db(){
    find "$WATCH_PATH" | grep -E -i -x "$CALIBRE_PATTERN" | process_find
}



function watch(){
    # 监听 rslsync 目录,忽略 .sync
    inotifywait -e close_write -e moved_to -mr --timefmt '%d/%m/%y %H:%M' --format "[%T %e] %w%f" "$WATCH_PATH" --exclude ".sync" | process_inotify
}
# init_db
watch

systemd server /etc/systemd/system/calibre-helper.service

[Unit]
After=rslsync.service

[Service]
ExecStart=/home/tiou/scripts/calibre_helper.sh

[Install]
WantedBy=default.target%
keyboard_arrow_up