Posted at

S3の複数ファイルをbashでテキスト処理する


概要

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バッチオペレーションをつかいましょう。