2022-01-21 , ,

TermuxのrcloneでDropboxと双方向同期

引き続きTermuxの環境構築をしています。

Dropboxが使いたかったのですが当然のことながら公式アプリで同期、なんてできません。検索したらrcloneというツールでクラウドストレージとやりとりできるそうです。

How to access dropbox files via termux? : termux

rcloneは pkg install rclone でインストールできて、設定も対話形式で簡単です。

ただ、双方向同期のような機能はありません。ああいうのはちゃんとやろうとすると結構大変ですからね。

代わりと言っては何ですが、diffとpatchで同期する仕組みを作ってみました。

  1. まずリモートの同期対象ディレクトリをrcloneでローカルの最新リモート置き場に取りこみます。
  2. 前回取りこんだ内容とdiffを取って、それをローカルのワーキングコピーにpatchします。
  3. うまく当たらないハンクがあったらここで終了。手動で解決してもらいます。
  4. うまく当たったら、最新のリモートとローカルのワーキングコピーのdiffを取って表示し、ユーザーに確認を促します。
  5. 問題ないようなら最新のリモートファイルを置く場所にローカルのワーキングコピーをコピーして、それをrcloneでアップロードします。

この作業の間に別PCがリモートを書き替えたら……THE ENDですw。

あとバイナリファイルとかもどうなるか知りません。

限定されたディレクトリで使う分には大丈夫でしょう。Dropboxなら消してしまってもすぐに気がつけば復元できるはずですしね。

#!/bin/bash

DROPBOXDIR=~/Dropbox
SYNCTARGET=sync-test-dir

set -eu

# Ensure Current Directory
cd "$(dirname "$0")"

# Pull Remote Files (Destructive)
# _remote(old) => _remote.before_pull
# remote => _remote
rm -fR _remote.before_pull
if [ -e _remote ]; then
    cp -a _remote _remote.before_pull
fi
rclone sync dropbox:${SYNCTARGET} _remote/${SYNCTARGET}

# Create Remote Diff (Non Destructive)
set +e
diff -urN _remote.before_pull/${SYNCTARGET} _remote/${SYNCTARGET} >_remote.diff
REMOTE_DIFF_STATUS=$?
if [ $REMOTE_DIFF_STATUS -ge 2 ] ; then
    exit 2
fi
set -e
#rm -fR _remote.before_pull

# Apply Remote Changes to Local (Destructive)
# _remote(new) => _last_pull
# (local) => _local.before_remote_change
# (remote changes) => (local)
if [ $REMOTE_DIFF_STATUS -eq 0 ] ; then
    echo "No Remote changes."
else
    # Save Last Pull State
    rm -fR _last_pull
    cp -a _remote _last_pull

    # Backup Local
    rm -fR _local.before_remote_change/${SYNCTARGET}
    if [ -e ${DROPBOXDIR}/${SYNCTARGET} ] ; then
        mkdir -p _local.before_remote_change/${SYNCTARGET}
        cp -a ${DROPBOXDIR}/${SYNCTARGET} _local.before_remote_change/${SYNCTARGET}
    fi

    # Apply Remote Changes to Local
    echo "Apply remote changes."
    mkdir -p ${DROPBOXDIR}/${SYNCTARGET}
    patch --set-time -p2 -d ${DROPBOXDIR}/${SYNCTARGET} < _remote.diff
fi

# Check Local Changes (Non Destructive)
set +e
diff -urN _remote/${SYNCTARGET} ${DROPBOXDIR}/${SYNCTARGET} >_local.diff
LOCAL_DIFF_STATUS=$?
if [ $LOCAL_DIFF_STATUS -ge 2 ] ; then
    exit 2
fi
if [ $LOCAL_DIFF_STATUS -eq 0 ] ; then
    echo "No local changes."
    exit $LOCAL_DIFF_STATUS
fi
# Confirm to Upload Local Changes
echo "You have local changes."

function confirm_local_changes {
    while true; do
        read -n1 -p "Upload? (Y/n/=): " yn
        case $yn in
            [Yy])
                return 0
                ;;
            [Nn])
                return 1
                ;;
            [=])
                emacsclient _local.diff
                ;;
        esac
    done
}

confirm_local_changes
if [ $? -ne 0 ]; then
    echo "Not uploaded."
    exit 1;
fi

# Apply Local Changes (Destructive)
# _remote(new) => _remote.before_local_change
# (local)(new) => _remote
# (local)(new) => _last_pull
rm -fR _remote.before_local_change/${SYNCTARGET}
mkdir -p _remote.before_local_change/${SYNCTARGET}
mv _remote/${SYNCTARGET} _remote.before_local_change/${SYNCTARGET}
mkdir -p _remote/${SYNCTARGET}
cp -a ${DROPBOXDIR}/${SYNCTARGET} _remote
rm -fR _last_pull/${SYNCTARGET}
mkdir -p _last_pull/${SYNCTARGET}
cp -a ${DROPBOXDIR}/${SYNCTARGET} _last_pull

# Upload Local Changes 
rclone sync -i _remote/${SYNCTARGET} dropbox:${SYNCTARGET}

双方向同期でなくてもこのrcloneは結構便利ですね。ちょっとしたファイルのやりとりが気軽にできます。

Pingback / Trackback