概要
S3のファイルを一括処理したい場合S3バッチオペレーションのlambdaを利用するのがクラウド的だと思うのですが、調べるのが面倒だったので シェルでやります。
環境
awscliをpythonのvenvにinstallしています。
credentialの設定も完了しているものとします。
$ sw_vers
ProductName: Mac OS X
ProductVersion: 10.14.5
BuildVersion: 18F132
$ python --version
Python 3.7.3
$ aws --version
aws-cli/1.16.245 Python/3.7.3 Darwin/18.6.0 botocore/1.12.235
やること
json形式のログを集めてS3に保存しているのですが、エントリーとエントリーの間に改行を入れておらず、扱いにくい状態でした。
before
{"hoge": "fuga"}{"hoge": "piyo"}
やりたいのは次のようにエントリーの間に改行を入れる簡単なテキスト処理です。
after
{"hoge": "fuga"}
{"hoge": "piyo"}
これがS3にs3://bucket-name/2019/01/01/00/filename
のような形式で集積されています。
内容
簡単なテキスト処理なのでシェルでやってしまいたいです。
ローカルファイル
ファイルがローカルだと次のようにすると思います。
FILE='./file-name'
cat ${FILE} | sed 's/}{/}\'$'\n{/g' > ${FILE}_out
S3の単一ファイル
AWSCLIではS3のファイルを標準出力にコピーできる & 標準入力をS3のファイルに保存できるので、同じように処理できます。
FILE='s3://bucket-name/2019/01/01/00/file-name'
aws s3 cp ${FILE} - | sed 's/}{/}\'$'\n{/g' | aws s3 cp - ${FILE}
S3の複数ファイル
指定のフォルダ以下を再帰で探索して先述の処理を実施します。
&
とwait
で並列実行しても良いかもしれません。
# !/bin/bash
function dfs () {
echo ${1}
if [ $(echo ${1} | rev | cut -c1) != '/' ]; then
aws s3 cp ${1} - | sed 's/}{/}\'$'\n{/g' | aws s3 cp - ${1}
return
fi
for deeper in $(aws s3 ls ${1} | rev | cut -f1 -d' ' | rev);
do
dfs ${1}$deeper
done
}
dfs 's3://bucket-name/'
まとめ
やっぱり非効率的なのでS3バッチオペレーションをつかいましょう。