ようへいの日々精進XP

よかろうもん

S3 バケットに保存されている画像ファイルのファイルサイズや大きさ (縦横) の一覧を取得する方法の一例

この記事は

YAMAP エンジニア Advent Calendar 2020 の六日目になる予定です。

qiita.com

tl;dr

ギョームにて、S3 バケットに保存されている画像ファイルのファイルサイズや大きさの一覧が欲しいというリクエストを頂きましたので、AWS CLIgrepawk 等のトラディショナルなツール、たまに Python スクリプトを駆使してリストアップしてみたのでメモしておきます。

尚、本記事で登場するツールのバージョンについては、以下の通りです。

$ sw_vers
ProductName:    Mac OS X
ProductVersion: 10.15.7
BuildVersion:   19H15

$ aws --version
aws-cli/2.1.1 Python/3.9.0 Darwin/19.6.0 source/x86_64

$ docker run --rm -t -i python:buster python --version
Python 3.9.0

尚、ここで書いてあるコマンドやシェルスクリプトは、あくまでも一例であり、他の実装があれば、是非、コメント等いただけると嬉しいです。

ファイルサイズ

シンプルに一覧を取得

#
# * --recursive: 再帰的にリストを出力する
# * --human: ファイルサイズに単位を付与して出力する
# * --sum: サマリー (オブジェクト個数と合計サイズ) を出力する
#

$ aws s3 ls s3://${BUCKET}/${OBJECT_PATH}/ --recursive --human --sum

以下のように出力されます。

...
2020-09-27 18:09:07  527.4 KiB /path/to/image1.png
2020-09-27 18:09:07    1.0 MiB /path/to/image2.png

Total Objects: 8436
   Total Size: 1.6 GiB

こちらでも一覧を取得できます。

fish> env AWS_PAGER="" aws s3api list-objects-v2 --bucket=${BUCKET} \
  --query='Contents[].[LastModified, Size, Key]' --output=text

以下のように出力されます。

--human 相当のオプションが存在していないことが残念です。2 列目がオブジェクトのサイズで、単位は bytes となります。

2020-09-27T09:09:07+00:00       540036  /path/to/image1.png
2020-09-27T09:09:07+00:00       1055619 /path/to/image2.png

env AWS_PAGER="" としているのは、AWS CLI v2 はデフォルトでページャーが有効になっているので、これを一時的に無効にしています。

MiB 及び GiB サイズの一覧を取得

MiB と GiB サイズの一覧を取得したい場合には、以下のように実行します。

$ aws s3 ls s3://${BUCKET}/${OBJECT_PATH}/ --recursive --human --sum \
  | egrep 'MiB|GiB' \
  | grep -v 'Total Size:' \
  | sort -k3 -r

また、容量が大きい順にソートして出力するように調整しています。

以下のように出力されます。

2020-05-08 15:55:40   26.9 MiB  /path/to/image1.png
2020-11-19 23:18:22   16.5 MiB /path/to/image2.png
...
2020-08-19 21:32:30    1.0 MiB /path/to/image099.png
2020-08-19 21:33:38    1.0 MiB /path/to/image100.png

100KiB 以下の一覧を取得

100KiB 以上のオブジェクトの一覧を取得した場合には、以下のように実行します。

aws s3 ls s3://${BUCKET}/${OBJECT_PATH}/ --recursive --human --sum \
  | egrep 'KiB' \
  | grep -v 'Total Size:' \
  | sort -k3 -r \
  | awk '$3 < 100.0{print}'

以下のように出力されます。

2020-09-02 14:08:18   99.9 KiB  /path/to/image1.png
2020-11-20 18:13:43   99.8 KiB  /path/to/image2.png
...
2020-05-08 15:41:50    1.3 KiB /path/to/image099.png
2019-10-10 17:27:04    1.3 KiB /path/to/image100.png

awkawk '$3 < 100.0{print}' こう書くことで、対象列の数値比較が出来ることを初めて知りました。

大きさ (縦横)

残念ながら

AWSAPI で取得する方法を見つけることが出来ませんでしたので、Python と boto3 を使うことにしました。

雑な Python スクリプト

以下のように雑な Python スクリプトを書きました。このスクリプトを適当なファイル名で保存します。(今回は check.py としました。)

from PIL import Image
import boto3

s3 = boto3.client('s3')

bucket = 'YOUR-BUCKET-NAME'
f = open('IMAGE-LIST')
lines = f.readlines()
for line in lines:
    key = line.replace('\n' , '')
    local = '/tmp/' + line.split('/')[-1]
    s3.download_file(bucket, key, local)
    im = Image.open(local)
    width, height = im.size
    
    print("key: %s, height: %s, width: %s" % (key, height, width))

画像ファイルの縦、横サイズを取得する為、Pillow というライブラリを利用しました。

また、IMAGE-LIST は、以下のコマンドで取得したオブジェクトの一覧が記載されたファイルとなります。

$ aws s3 ls s3://${BUCKET}/${OBJECT_PATH}/ --recursive --human --sum | awk '{print $5}' > IMAGE-LIST
$ cat IMAGE-LIST
 /path/to/image1.png
 /path/to/image2.png
...
 /path/to/image099.png
 /path/to/image100.png

一旦、この Python スクリプトを使って、全ての画像ファイルの縦横サイズを取得します。

$ docker run -t -i --rm -v $PWD:/work python:buster bash
docker> pip install Pillow boto3
docker> python check.py
key:  /path/to/image1.png, height: 150, width: 150
key:  /path/to/image2.png, height: 576, width: 1024
...

いい感じです。縦 (height) と横 (width) とオブジェクトキー (ファイル名) が出力されました。

以上

こういう細かいけど、なんとなくエンジニアリングな作業が大好きです。また、上記以外にも様々な実装がありそうなので、ワクワク感もたまりませんな。

以上、素敵な S3 バケットライフをお過ごし下さい。

参考

stackoverflow.com