CUI Dropboxクライアント dbxcli を使ってファイルをアップロードしてみた

2019-11-17

特定のファイル、ディレクトリの中身だけをDropboxで同期したいと思ったことはありますか?

私の場合はLinuxサーバのバックアップを保存しておくためのストレージとしてDropboxを使いたかったんですが、 Linux用のDropboxデーモンでは除外設定はあるものの、特定のディレクトリだけを同期する方法はないし、 対象以外全部除外するのはあまり現実的な方法ではないでしょう。

あと dropboxd をずっと起動しておくのも気持ち悪い。

そこで 非同期でDropboxを操作するクライアントを探していたら Dropbox謹製のGolang製クライアントがありました。 (ただ、内部で使ってるdropbox-sdk は unofficialっぽい)

dbxcli

環境にあったバイナリを Releases からダウンロードして配置して実行権限を設定するだけです(ファイル名を変えてもOK)

$ wget https://github.com/dropbox/dbxcli/releases/download/v3.0.0/dbxcli-linux-amd64
$ chmod +x dbxcli-linux-amd64
$ ./dbxcli-linux-amd64
Use dbxcli to quickly interact with your Dropbox, upload/download files,
manage your team and more. It is easy, scriptable and works on all platforms!

Usage:
  dbxcli [command]

Available Commands:
  account     Display account information
  cp          Copy a file or folder to a different location in the user's Dropbox. If the source path is a folder all its contents will be copied.
  du          Display usage information
  get         Download a file
  help        Help about any command
  logout      Log out of the current session
  ls          List files and folders
  mkdir       Create a new directory
  mv          Move files
  put         Upload files
  restore     Restore files
  revs        List file revisions
  rm          Remove files
  search      Search
  share       Sharing commands
  team        Team management commands
  version     Print version information

Flags:
      --as-member string   Member ID to perform action as
  -h, --help               help for dbxcli
  -v, --verbose            Enable verbose logging

Use "dbxcli [command] --help" for more information about a command.

コマンドはなんとなくヘルプ見ればわかると思うので全ては解説しませんが、 個人的に重要だと思う accountput について簡単に解説します。

dbxcli と dropbox を紐付け、その情報を閲覧するのが account です。

最初に実行すると 認証用のURLと Enter the authorization code here: というメッセージが表示されるので、

./dropbox-token.png

URLにアクセスして取得した認証コードを貼り付ければ紐付け完了です。

$ ./dbxcli-linux-amd64 account
1. Go to https://www.dropbox.com/1/oauth2/authorize?client_id=AAAAAAAAAAAAAAAA&response_type=code&state=state
2. Click "Allow" (you might have to log in first).
3. Copy the authorization code.
Enter the authorization code here: BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
Logged in as User name <username@example.com>

Account Id:        dbid:CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
Account Type:      pro
Locale:            en
Referral Link:     https://www.dropbox.com/referrals/DDDDDDDDDDDDDDDDDDDDDDDDD-8?src=app9-999999
Profile Photo Url:
Paired Account:    false

put はファイルをアップロードするためのコマンドです。

$ ./dbxcli-linux-amd64 put --help
Upload files

Usage:
  dbxcli put [flags] <source> [<target>]

Flags:
  -h, --help   help for put

Global Flags:
      --as-member string   Member ID to perform action as
  -v, --verbose            Enable verbose logging

アップロード ファイルのパスが必須で、アップロード のパス(Dropbox側) は省略が可能です。

アップロード先を省略すると Dropboxのルートディレクトリ直下にコピーされるので注意しましょう。

# アップロード先はファイル名まで指定しなければいけない
$ ./dbxcli-linux-amd64 put test.txt test
Uploading 4 B/4 B
Error: path/conflict/folder/

$ ./dbxcli-linux-amd64 put test.txt test/test.txt
Uploading 4 B/4 B

test/test.txt がアップロードされてますね。

./dropbox-uploaded.png

さて、ディレクトリごとアップロードできるのか? という疑問が湧いてきますが、残念ながらできません。

当該クライアントはDropboxのAPIをラップしているだけなのでディレクトリのアップロードは 利用者が再帰的にディレクトリを走査して実行してくれという方針なんでしょう。

ということでアップロードするシェルスクリプトを簡単に作りました。

#!/bin/bash

DST_ROOT="backups"
SRC_ROOT="./images/"

if [ "$1" != "" ]; then
  SRC_ROOT="${SRC_ROOT}/$1"
fi

if [ "$2" != "" ]; then
  SRC_ROOT="${SRC_ROOT}/$2"
fi

if [ "$3" != "" ]; then
  SRC_ROOT="${SRC_ROOT}/$3"
fi

echo ROOT: $SRC_ROOT
find $SRC_ROOT -type f 2>/dev/null | while read FILE
do
  echo ==== $FILE ====
  ./dbxcli-linux-amd64 put ${FILE} "${DST_ROOT}/${FILE#*/}"
done

私の場合は日次で自動実行することを想定してディレクトリを区切っています。

手動実行では年単位、月単位でも実行したくなる可能性があるので、 年月日を引数で渡せるようにスクリプトを作りました。

警告

bash であれば パス内に カレントディレクトリを意味する単体の . や 連続する / があっても処理してくれますが、 アップロード先のパスにこのような文字列があると Error: json: cannot unmarshal object into Go value of type string というエラーがかえってくるので、 前もってパスを整形しておきましょう。 (JSON化のエラーメッセージなのはよくわからん

NG:

/path/./to/file

NG:

/path//to/file

OK:

/path/to/file (先頭のスラッシュはあってもなくてもどちらでもよい)

ちなみに実行するとこんな感じになります(ちゃんとアップロードされてました)

$ ./upload.sh $(date "+%Y")
ROOT: ./images/2019
==== ./images/2019/10/20/2/image.png ====
Uploading 5.8 KiB/5.8 KiB
==== ./images/2019/10/20/2/thumb_image.png ====
Uploading 5.4 KiB/5.4 KiB
==== ./images/2019/10/20/2/thumb100_image.png ====
Uploading 2.2 KiB/2.2 KiB

備考

cp コマンドはDropbox上のファイルをコピーする操作です。

Dropbox上のファイル(ディレクトリ)をコピーして Dropbox上に配置するだけなのでアップロードには使えません。

当然自動同期に比べるとちまちまとめんどくさいですが、 バックアップ用途では小回りがきくこちらのほうが向いている気がします。