iPhone写真をDropbox/CentOSで同期管理する §2

iPhoneで撮った写真をDropbox on CentOSで同期管理する §2 Dropboxのファイル名を置換しながらコピーする
前回 に引き続き、iPhone→Dropbox→サーバ→欲しい写真だけを集めたディレクトリへと半自動的に同期管理させる方法を考える。前回はDropbox CLIとImageMagickのインストールを行い、サーバ上に全画像を同期させ、ピクセル数から判定したファイルを抽出(echoで確認)した。
今回はDropboxから取得したファイルを管理用ディレクトリにコピーする方法を考える。

ところでこれを見てくれ。こいつをどう思う

1
2
% ls ~/Dropbox/カメラアップロード
2012-02-22 12.46.00.jpg 2012-06-30 09.24.48.jpg 2012-08-15 08.00.58.jpg........................(ry

凄く・・・半角スペースです・・・。
前回でも書いたとおり、半角スペースがファイル名に入っている。このままコピーをしてしまうとhtmlから参照できなかったり、これからの運用のためにいろいろと面倒であること請け合い。
なのでコピー時にリネームをする必要がある。
また、欲を言えばピリオドも置換したいところではあるが、半角スペースをアンダースコアに変更するつもりなので、アンダースコア以外の文字にしたい。
なぜなら、逆方向の変換、デコードを行う際に位置によって半角スペースに戻したりピリオドに戻さなければならないからだ。
しかしながら、ハイフンはすでにオリジナル画像名に使われているので、今回はハイフンでもアンダースコアでもなく、イコールに置換することとした。

文字列置換の方法を考察

shellスクリプトで利用できる文字列変換といえば、sedが有名だが、
shellスクリプト変数のパラメータ展開でも実行可能である。sedは正規表現を利用でき、echo $変数名 | sed -e "s/regexp/substitute_string/" の書式で文字列置換が出来る。
パラメータ展開は比較的知名度が低いようだが、単純な置換においては記述が簡易で高速(らしい)。
パラメータ展開についてはこちらのブログ記事が非常にわかりやすかったので、参照してください。
ではどちらが今回の方法に適しているのか、実際にDropboxから対象ファイルを抽出し、そのファイル名文字列を置換した後、そのファイルがコピー先に無い場合にechoする(後々ここをcpにする)スクリプトを、
sed版とパラメータ展開版で書き、実行してみる。

まずはsedの場合

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#!/bin/bash
files=`find ~/Dropbox/カメラアップロード -type f | grep \.jpg`
(IFS=$'\n';
for i in ${files}; do
width=`identify -format "%w" ${i}`
height=`identify -format "%h" ${i}`
if [ ${width} = ${height} ]; then
fname=${i##*/}
dist_fname=`echo $fname | sed -e "s/\ /_/" | sed -e "s/\.[^jpg]/=/g"`
distname="~/dist/"$dist_fname

#isExists file?
if [ ! -e ${distname} ]; then
echo "source: "${i}" dist: "${distname}
fi
fi
done
)
echo "done ps.";

置換を行っているのは9行目。半角スペースをアンダースコアに、.jpg以外のピリオドをイコールに変換している。

次に、パラメータ展開の場合

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#!/bin/bash
files=`find ~/Dropbox/カメラアップロード -type f | grep \.jpg`
(IFS=$'\n';
for i in ${files}; do
width=`identify -format "%w" ${i}`
height=`identify -format "%h" ${i}`
if [ ${width} = ${height} ]; then
fname=${i##*/}
dist_fname=${fname/\ /_}
dist_fname=${dist_fname//\./=}
dist_fname=${dist_fname/-jpg/\.jpg}
distname="~/dist/"$dist_fname
#isExists file?
if [ ! -e ${distname} ]; then
echo "source: "${i}" dist: "${distname}
fi
fi
done
)
echo "done ps."

こちらは正規表現が使えないので、スペース置換、ピリオド全置換、suffixのピリオドの戻し、の3段置換になる。

どちらも期待する置換結果が得られることを確認したうえで、実行時間を計ってみる。スクリプトの開始と終了にdateで時間を秒精度で出力させ、なんどか同じ処理を実行させる。

sed:21~22秒(22秒がほとんど)

パラメータ展開:20~21秒(半々くらい

微妙な差だ・・・・・。

Dropboxへのアップロードスパンを考慮するとファイルの同期処理はcronで日次実行が妥当だと思われる。
すると一日に撮った写真の枚数分置換処理が動く計算になるので、運用上は多くても数十回程度の文字列置換処理に収まるはず。
今回の時間測定では、文字列置換をしたファイル数は450件弱だったので、それで1秒強程度の差しかでないのであれば、実行時間が早い/遅いという議論があまり意味を持たない。
むしろ1行で記述できているsedのほうがスマートなスクリプトのように思えるため、今回のリネームの処理は、sedを用いた文字列置換によって実装することにした。

今回はsed、パラメータ展開、あとさらっと書いてるけど if [ ! -e $file_name] 構文による存在チェックの利用方法が学べた。

次回は逆方向の処理、すなわちDropbox上から削除されたファイルの削除処理に関連した処理と、ログ出力を考える。


iPhone写真をDropbox/CentOSで同期管理する §1

iPhoneで撮った写真をDropbox on CentOSで同期管理する§1 DropboxとImagemagickのインストール、対象ファイルの抽出
写真に適用できるフィルタのパターンや、サービスの動作状況(たまに落ちてるサービスが多い)によってiPhoneで撮影する写真アプリがInstagramだったりPathだったりするが、写真を撮るたびに管理用のストレージサービスや写真系SNSにポストするのは非常に面倒。面倒になるとだんだんやらなくなってしまって結局散在箇所が増えるだけになってしまうので、意識せずに自分のサーバ上にアップできるようにしたい。面倒は敵。

でもそれ、(容量制限を無視すれば)iCloud/フォトストリームでことが足りるじゃん、なのだが、写真アプリがカメラロール上に保存する「原画像」と「フィルタを適用したシャレオツ画像」のうち、
「フィルタを適用したシャレオツ画像」のみを抽出してひとつのディレクトリにまとめる**というのもやってしまいたい。
ということでLet’s Try Hack.

iPhoneの下準備

iPhoneからDropboxに画像を保存するにはアプリを起動して「設定(歯車アイコン)> カメラアップロード」をオンにする。
バックグラウンドでのアップロード許可をすると電池がもたなそうなのでこれはオフしておく(電池切れで撮影できなくなっては自爆。また、パズドラのために電源確保は重要です)。

Dropbox

CentOSにDropbox CLIをインストールする

ほぼこちらの手順どおり。
Python2.6以上が必要ですが、僕のサーバにはインストールされておりました。
wgetでCLIツールを取得して、あとはお任せするだけ。簡単。PATHを通すために$HOME/bin (通常は.bash_profileにPATH指定されている)に配置している。

1
2
3
4
5
6
7
% mkdir ~/bin/
% python --version
Python 2.7.
% wget -O ~/bin/dropbox.py http://www.dropbox.com/download?dl=packages/dropbox.py
% chmod a+x ~/bin/dropbox.py
% dropbox.py
% dropbox.py start -i

初回でサービスを起動するとこのURLからクライアントのリンクを承認してね、みたいなのが出るので、アクセスする。

1
2
3
% dropbox.py start
To link this computer to a dropbox account, visit the following url:
https://www.dropbox.com/cli_link?host_id=youraccountkeyhogefoobar

認証が成功すればサービスが起動できる。~/Dropbox/ にどんどんとデータが同期されているのを確認すればOK。
コマンドの使い方は先のページを参考にし、
同期対象が ~/Dropbox/カメラアップロード/ になるように同期除外設定を施した。

ImageMagickのインストール

ImageMagickは画像のデータをbashから直接扱うライブラリとしては大御所。
今回は画像の縦横のピクセルを取得するためにインストールする。後々サイズ変更スクリプトなんかにも使える。
PathやInstagramは正方形の画像を標準で生成するため、縦横のピクセル数が一致する画像のみをDropBoxディレクトリから管理ディレクトリにコピーさせることで、シャレオツ画像だけの塊を作ることが出来る。

インストールはこちらに書かれている通り、ソースからmake / make installした。とても簡単。

1
2
3
4
5
6
7
8
% yum install libjpeg-devel libpng-devel
% wget http://www.imagemagick.org/download/ImageMagick.tar.gz
% tar zxvf ImageMagick.tar.gz
% cd ImageMagickImageMagick-6.8.6-9
% ./configure
% make
% make install
% make clean

取得したファイルを分類してみる

そうこうしているうちにDropBoxの同期がだいぶ進んでいるのでbashでコピースクリプトを実行する。
DropBoxが生成するディレクトリ名は日本語になっているが、サーバの言語設定を日本語にしているので、一応扱える。
言語設定は /etc/sysconfig/i18n で確認できる。LANG="C" がデフォルトだが、これを "ja_JP.UTF-8"にするとコマンド結果などが日本語化される。

1
2
3
4
%cat /etc/sysconfig/i18n
#LANG="C";
LANG="ja_JP.UTF-8";
SYSFONT="latarcyrheb-sun16";

また、同期する写真ファイル名に半角スペースが入る。これが意外と厄介で、全ファイルのリストをfindで取得して変数に代入すると、
1行のfind結果が2つの値に分解されてしまう。これを解消するために、コマンドの区切り文字を改行のみにする環境変数設定をスクリプトのブロック内で定義してあげるとよい。
下のサンプルではfind結果1行ごとにファイルのwidth(px)、height(px)を取得して一致したらechoしている。
identifyがImageMagickによって提供されるコマンドで、フォーマット指定”%w”、”%h”によってそれぞれ出力させている。

まずはここまで。実は”ファイル名に半角スペース問題”でかなりの時間を取られてしまった。解決法は以前に見たことのあるページだったので、昔の失敗が全然活かせていないorz。反省。



RubyよくわかんないけどOctopressでブログ構築してみる

Rubyをいじったことがないので環境周りからよくわからないけど、Github Pagesにブログを構築してみるテスト。
LolipopさんのWordpressがものすごい苛められた記念。

Rubyまわりを整備する

1.rvmの確認

rvmはインストールされていたけれどPATHが通っていなかったので、~/.bash_profileに追記

1
2
3
4
5
% vi ~/.bash_profile
PATH=PATH:/usr/local/rvm/bin/
% source ~/.bash_profile
% rvm -v
rvm 1.22.3 (stable) by Wayne E. Seguin <wayneeseguin@gmail.com>, Michal Papis <mpapis@gmail.com> [https://rvm.io/]

2.ruby 1.9.3の用意 rvmでインストール。

1
2
3
4
5
% rvm install 1.9.3
% rvm list knwon
% rvm --default 1.9.3
% ruby -v
ruby 1.9.3p448 (2013-06-27 revision 41675) [x86_64-linux]

Octopressを使う

 いろいろ調べたけどRubyとJekyllとOctopressの関係がよくわからんのでおっかなびっくりしながら。
てかRubyのことまったく知らなかったので頭の中は「rake is 何」、「gem is 何」でいっぱいいっぱい。
いろんなブログを参考にさせていただいた。

 要はRuby1.9.3入れて、Octopressをgitから落として、rakeでビルドとデプロイすればいいってことでした。

Octopressをインストールする (+ カスタムテーマもいれておく)

カスタムテーマは こちら にある。
octopress/.themes/にgitからcloneしてきたら、rake install['theme name'] で適用してあげればよい。

“user_name.github.com”のリポジトリは作っておく。つくったら何もしない(デプロイするとき競合しないようにするので、重要)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
% cd /path/to/blog
% git clone git://github.com/imathis/octopress.git octopress
% cd octopress
% gem install bundler
% bundle install
% rake install
% rake setup_github_pages
## githubのリポジトリ名の入力が促される。sshのURLで入れること!!!

## greyjoyのテーマを入れる。
% git clone git://github.com/rezajatnika/greyjoy.git .themes/greyjoy
% rake install[greyjoy]

## 最低限の設定をする。
% vi _config.yml
# ----------------------- #
# Main Configs #
# ----------------------- #
url: http://shoota.github.io
title: Anaguma
subtitle: いろいろ試してみる.
author: shoota
simple_search: http://google.com/search
.....and more

## Jekyllでページをつくってgithubにpush
% rake generate
% rake deploy

% rake setup_github_pages で指定するのが git://********/.git じゃなきゃいけないせいで非常につまった。sshで接続するためのRSA keyも登録していなかったので、
~/.ssh/ にRSAをつくってgithubのアカウントにセッティング。 ちゃんとやってるつもりなのにうまくいかなかったりして、ここが一番焦ったわ….
リポジトリ作るの失敗したのかと思ってREADME.mdをpushしたらrake deployでrejectされるし…… ともあれ、http://shoota.github.io/ に無事に作られた。

使ってみた感想

Macでやればよかった。

そもそもサーバ上でやることじゃなかった。書きながらlocalhost:4000で確認するのが前提。サーバの余計なポート空けたくなかったのでちょっとした変更とか、テーマ変えるたびにpushした。しんどい。

ブログ書き終わってから公開するまでめんどい*

単純なテストページをJekyllが吐き出してくれるのが3秒くらい。日々記事が増えたら結構時間かかりそう。当然、pushもします。その間僕はなにをしてたらいいのでしょうか。Github Pagesに反映されるのが1分くらい。すぐに記事が確認できないのは結構ストレスを感じたし、かといって確認せずには寝られないタチ。

結論=そこまで便利じゃなかったなぁ……

有償サービスですら攻撃受けて止まる昨今、無償のブログツールに多くを求めちゃいけない。技術的には非常に面白いので、やってみて非常に勉強になりました。Rubyもインストールしたしね。