Amazon S3 Select を利用して S3 に格納してある csv ファイルのレコード数を取得してみました。
使い方
レコード内に改行コードが含まれていても、1レコードとしてカウントされます。
KEY_PATH
がフォルダなら再帰的に検索してくれます。
$ s3_cnt
Usage: s3_cnt [BUCKET_NAME] [KEY_PATH]
$ s3_cnt hoge-bucket hoge/fuga/
hoge/fuga/test1.csv : 100
hoge/fuga/test2.csv : 1022
hoge/fuga/foo/test3.csv : 100
hoge/fuga/foo/bar/test4.csv : 200
前準備
インストールしておいてください。
スクリプト作成
利用環境
$ cat /etc/system-release
Amazon Linux 2
$ python -V
Python 2.7.14
Python
s3_cnt.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import argparse
import boto3
def get_args():
parser = argparse.ArgumentParser()
parser.add_argument("bucket", help="input bucket name", type=str)
parser.add_argument("key_path", help="input file path", type=str)
args = parser.parse_args()
return(args)
def get_s3_response(bucket, path):
s3 = boto3.client( 's3', 'ap-northeast-1')
response = s3.select_object_content(
Bucket = bucket,
Key = path,
ExpressionType = 'SQL',
Expression = 'Select COUNT(1) from S3Object s',
InputSerialization = {
'CompressionType': 'NONE',
'CSV': {
'FileHeaderInfo' : 'Use',
'RecordDelimiter' : '\n',
'FieldDelimiter' : ',',
'AllowQuotedRecordDelimiter' : True # Falseだと改行コードでレコードが分かれる
}
},
OutputSerialization = {
'CSV': {
'RecordDelimiter' : '\n',
'FieldDelimiter' : ','
}
}
)
return(response)
def main():
args = get_args()
response = get_s3_response(args.bucket, args.key_path)
for event in response[ 'Payload' ]:
if 'Records' in event:
records = event[ 'Records' ][ 'Payload' ].decode( 'utf-8' )
print( records )
if __name__ == '__main__':
main()
Bash
s3_cnt.py
と s3_cnt.sh
は同階層に置いてください。
s3_cnt.sh
#!/bin/bash
if [ $# -ne 2 ]; then
echo "Usage: $0 [BUCKET_NAME] [KEY_PATH]" 1>&2
exit 1
fi
FULL_PATH=$(realpath $0)
cd $(dirname $FULL_PATH)
BUCKET_NAME=$1
KEY_PATH=$2
S3_ARRAY=`aws s3 ls $BUCKET_NAME/$KEY_PATH --recursive`
CSV_ARRAY=()
for data in ${S3_ARRAY[@]}; do
if echo $data | grep -q '.csv' ; then
RECORD_VAL=`python s3_cnt.py $BUCKET_NAME $data`
echo -e "$data : \t$RECORD_VAL"
fi
done
exit 0
シンボリックリンク張る
$ ln -s /usr/local/bin/s3_cnt /path/to/s3_cnt/s3_cnt.sh
以上