Mac下fswatch+shell实现简悦导出markdown到obsidian

一、先看效果

1 . 先打开你的网页,并进入简悦阅读模式,选择动作->导出为 Markdown 格

Mac+fswatch+shell实现简悦markdown导出到obsidian-20240303122736440.webp

2 . 等待下载完成后,会弹出下面的窗口

Mac+fswatch+shell实现简悦markdown导出到obsidian-20240303123020503.webp

选择好目录后,shell 脚本会自动把刚才下载的 markdwon 文件移动到你选择的文件夹内;

选择取消,退出话框,不移动文件。

3. 如果你不想每次都弹出窗口可以通过配置是否手动选择,并配置好自动移动的目标文件夹后即可,不会弹出窗口,后台自动把你刚才下载的 Markdown 文件移动到你指定的文件夹中

具体配置下面会讲。

二、源代码及配置

源代码如下:

#!/bin/bash

# nohup /Users/yourname/bin/mdwatch.sh >/dev/null 2>&1 &
# * * * * * /bin/bash /Users/yourname/bin/mdwatch.sh >/dev/null 2>&1 &

# 配置下载文件的路径和你的仓库文件夹路径

# 你的fswatch的安装路径,必须是绝对路径
fswatch="/usr/local/bin/fswatch"

# 下载文件的目录,后面不加/
downloads_dir="/Users/yourname/Downloads"

# 你仓库的目录(注意不是文件夹的目录),后面不加/
vault_dir="/Users/yourname/Data/我的笔记"

folder_dir="" # 文件夹的路径(相对路径),为空为根目录,前面不要加/

manual='yes' # 是否手动选择保存? yes,则每次都要手动选择保存的文件夹,no,则自动保存到folder_dir变量指定的目录里

# 如果已启动则退出
pid=$(pgrep -f fswatch)
if [ -n "$pid" ]; then
    echo "已在运行,请不要重复启动!"
    exit 1
fi

# 监控文件夹变化
$fswatch -x --event Created "$downloads_dir" | while read line; do

    # 获取文件名
    file=$(echo "$line" | awk -F ' Created' '{print $1}') # /xx/yy/zz.md

    # 判断是否为md文件
    if [[ "$file" =~ \.md$ ]]; then

        target_dir=""

        # 获取文件夹路径
        if [ "$manual" == "yes" ]; then
            # 手动选择
            result=$(find "$vault_dir" -not -path '*/\.*' -type d -exec printf "%s/\n" {} + | sed "s|^$vault_dir||")
            result=$(echo $result)

            # 使用 IFS 空格来分割字符串,并将结果赋值给数组
            IFS=' ' read -ra options <<< "$result"

            # 将Bash数组转换为AppleScript可接受的格式
            escaped_options=$(IFS=','; echo "${options[*]}" | sed 's/,/","/g;s/^/"/;s/$/"/')

            # 使用AppleScript弹出选择列表
            read -r selectedOption < <(osascript -e "
                tell application \"System Events\"
                    activate
                    set userChoice to choose from list (${escaped_options}) with title \"请选择目标文件夹\" with prompt \"请选择:\"
                    return userChoice as text
                end tell
            ")

            if [ "$selectedOption" == "false" ]; then
                echo "用户放弃了文件移动"
                # osascript -e 'display dialog "您放弃了本次移动,您可以去下载文件夹手动移动!" buttons {"好的"} default button 1 with title "温馨提醒"'
            else
                target_dir="${vault_dir}${selectedOption}"
            fi
        else
            # 固定目录
            target_dir="$vault_dir/$folder_dir"
        fi

        # 移动文件,文件存在时重命名为副本
        if [ "$target_dir" != "" ]; then
            if [ ! -d "$target_dir" ]; then
                echo "${target_dir}不存在!"
                osascript -e "display alert \"${target_dir}不存在!\" buttons {\"好的\"} default button 1"
                continue
            fi
            filename=$(echo "$file" | awk -F '/' '{print $NF}') # zz.md
            if [ -f "$target_dir/$filename" ]; then
                ext=$(echo "$filename" | cut -d'.' -f2) # md
                filenameonly=$(echo "$filename" | cut -d'.' -f1) # zz
                current_date=$(date +%Y%m%d%H%M%S)
                random_number=$(( (RANDOM % 1000) + 1 ))
                echo "文件{$filename}改名成了$filenameonly-副本-$current_date-$random_number.$ext"

                mv "$file" "$target_dir/$filenameonly-副本-$current_date-$random_number.$ext"
            else
                mv "$file" "$target_dir/"
            fi
            echo "$filename 已保存成功!"
            osascript -e "display notification \"$filename 已保存成功!\" with title \"提示:\""
        fi
    fi
done

代码配置说明

  1. fswatch,downloads_dir,vault_dir 必须配置,且必须是绝对路径,路径后面不要加/
  2. folder_dir 如果不开启手动选择保存的时,默认保存的路径,为空代表仓库根目录,比如,你想保存到“网页剪藏”文件夹中,只需要 folder_dir="网页剪藏" 即可,下级目录这样配置 folder_dir="网页剪藏/图片收藏",注意,路径前面不要加/
  3. manual 参数代表是否手动选择保存? yes,则每次都要手动选择保存的文件夹,no,则自动保存到 folder_dir 变量指定的目录里
  4. 注意,以上路径需要根据自己的实际情况修改
  5. 该 shell 目前仅适用于 Mac 电脑,因为使用了 Mac 专用的 GUI 脚本

三、安装

  1. 先安装 fswatch 命令,终端执行 brew install fswatch 安装即可
  2. 复制上面的源码保存为 mdwatch.sh 即可

四、使用

  1. 直接使用,直接双击打开脚本就行(前提是脚本具有可执行权限,shell 下命令 chmod u+x mdwatch.sh 即可),但这种方式有一个黑色命令行窗口在终端里,且每次使用时需要打开
  2. 配合 shell commander 插件,每次启动 ob 时打开,这种方式必须当 ob 打开时才能使用
  3. 添加到系统登录启动里,这种方式同样有个命令窗口在终端里
  4. 配置 plist,让系统开机在后台运行,这种方式可能会意外退出进程,但通常不会退出
  5. crontab 方式启动(推荐),这种方式解决了以上所有问题,建议设为每分钟执行一次,不用担心这样会启动多个进程,该脚本已启动会忽略 cron 的再次调用,如果意外退出,最迟 1 分钟可自动恢复。
  6. crontab 的配置
    终端窗口输入 crontab -e,打开 vim 编辑窗口,输入 * * * * * /bin/bash /Users/yourname/bin/mdwatch.sh >/dev/null 2>&1 & 后保存即可。这里的 mdwatch.sh 脚本路径需要改成自己的。
  7. 运行状态检测,手动启动/重启,停止
    1. 查看运行状态: 终端执行 fgrep fswatch 命令,能正确显示 fswatch 进程号即正常运行
    2. 停止运行:先通过 fgrep fswatch 找到进程号,再通过 kill 进程号 杀死进程,fswatch 进程退出后 mdwatch.sh 会自动退出,反过来不会。注意:如果要彻底不需要了,还需要把 crontab 里的定时任务删除。
    3. 手动启动:执行命令 nohup /Users/yourname/bin/mdwatch.sh >/dev/null 2>&1 & 即可
    4. 手动重启:先停止运行,参考 2,再手动启动,参考 3
  8. Windows 暂不支持,有兴趣的可以到 Powershell监控文件夹创建md文件并移动位置 查看 powershell 的实现的思路

五、总结

看似复杂,其实很简单,因为掺杂了很多说明文字,所以显得复杂。

  1. 复制代码并创建 mdwatch.sh 脚本
  2. 编辑脚本修改下载路径和保存路径等
  3. 把脚本加入到 crontab 里

如果想马上运行,执行 nohup /Users/yourname/bin/mdwatch.sh 即可。