S3 オブジェクトの一覧をあまり手間をかけずに AWS CLI で取得する

S3 バケットに格納されたオブジェクトの一覧を aws a3 ls コマンドを使ってお手軽に取得します。デフォルトの出力結果だと少し余計な情報が入るため、ちょっとひと工夫を加えます。

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

S3 オブジェクトの一覧を取得したい

コンバンハ、千葉(幸)です。

S3 バケットに格納されているオブジェクトの一覧を取得したい、という時がありました。

単発の棚卸し的な用途であったため、そのために作り込みをしたり何かの機能を有効化したりしたくありません。AWS CLI が使えれば要件を満たせるかもと思って調べたところ、ひと工夫だけ必要であったためその足跡を残しておきます。

まとめ

以下コマンドを実行すれば比較的お手軽にオブジェクト一覧が取得できる。

aws s3 ls バケット名 --recursive | grep -v '/$' | awk '{print $4}' > result.txt
  • --recursiveオプションによって再帰的に一覧を取得している
  • grep -v '/$'によって「末尾が/」であるプレフィックスを結果から除外している
  • awk '{print $4}'によってオブジェクト名のみを出力している

アクセスキーの払い出しといった事前準備が不要なため、AWS CloudShell での実行がオススメです。わたしの環境では、約110万オブジェクトを対象にして実行したところおよそ 20 分で出力が完了しました。

aws s3 ls によるバケット内のオブジェクト一覧の出力

今回使用する aws s3 ls は、バケットの一覧もしくはオブジェクトの一覧を出力できるコマンドです。

バケットを引数に指定して実行すると、バケットのルート直下のオブジェクトを出力してくれます。「PRE」と表示されているのはプレフィックス(コンソールでは「フォルダ」と表現される)を表します。

$ aws s3 ls chibayuki-test-test
                           PRE folderA/
                           PRE folderB/
2023-02-27 12:48:13        750 test.json
2023-02-27 12:47:39          5 test.txt

↑プレフィックスは末尾が「/で表されます。

--recursiveオプションを付与することでプレフィックス配下のオブジェクトも再帰的に出力されます。

$ aws s3 ls chibayuki-test-test --recursive 
2023-02-27 12:48:30          0 folderA/
2023-02-27 12:51:16          5 folderA/test_a.txt
2023-02-27 12:48:52          0 folderB/
2023-02-27 12:51:33          5 folderB/test_b.txt
2023-02-27 12:48:13        750 test.json
2023-02-27 12:47:39          5 test.txt

今回はあまり関係ありませんが、以下オプションを付与することで少し嬉しい場合があります。

  • --summarizeオプション:オブジェクト数とトータルサイズのサマリを追加
  • --human-readableオプション:サイズを人間が読みやすい単位で表示
$ aws s3 ls chibayuki-test-test --recursive --summarize --human-readable 
2023-02-27 12:48:30    0 Bytes folderA/
2023-02-27 12:51:16    5 Bytes folderA/test_a.txt
2023-02-27 12:48:52    0 Bytes folderB/
2023-02-27 12:51:33    5 Bytes folderB/test_b.txt
2023-02-27 12:48:13  750 Bytes test.json
2023-02-27 12:47:39    5 Bytes test.txt

Total Objects: 6
   Total Size: 765 Bytes

特定のプレフィックス配下のオブジェクトのみを表示したいときは、引数にプレフィックスを追加します。

$ aws s3 ls chibayuki-test-test/folderA --recursive --summarize --human-readable 
2023-02-27 12:48:30    0 Bytes folderA/
2023-02-27 12:51:16    5 Bytes folderA/test_a.txt

Total Objects: 2
   Total Size: 5 Bytes

↑ここではchibayuki-test-test/folderA配下のみを表示しています。

aws s3 ls コマンドの出力結果を加工する

ここまで見てきた内容にひと工夫を加えれば、「オブジェクト一覧のみの出力」が実現できます。

grep -v '/$'で末尾が/であるプレフィックスを除外。

$ aws s3 ls chibayuki-test-test --recursive | grep -v '/$'
2023-02-27 12:51:16          5 folderA/test_a.txt
2023-02-27 12:51:33          5 folderB/test_b.txt
2023-02-27 12:48:13        750 test.json
2023-02-27 12:47:39          5 test.txt

awk '{print $4}'で 4 番目のカラムのみを出力。

$ aws s3 ls chibayuki-test-test --recursive | awk '{print $4}'
folderA/
folderA/test_a.txt
folderB/
folderB/test_b.txt
test.json
test.txt

組み合わせた結果を特定のファイル(ここではresult.txt)に出力。

$ aws s3 ls chibayuki-test-test --recursive | grep -v '/$' | awk '{print $4}' > result.txt                           
$ cat result.txt 
folderA/test_a.txt
folderB/test_b.txt
test.json
test.txt

もちろん作成日時やオブジェクトサイズを削らずに出力することも可能です。要件に応じてカスタマイズしてみてください。

110 万件の S3 オブジェクト一覧を出力してみた

オブジェクト数が大量であるときにも耐えうる手法なのかが気になったため、100万超のオブジェクトが格納された S3 バケットを対象に実行してみます。実行環境には AWS CloudShell を選択します。

オブジェクト数は S3 コンソールの「メトリクス→オブジェクトの合計数」や、Storage Lens のデフォルトダッシュボードから確認できます。

今回は Storage Lens の方から確認しました。1.1 M 、およそ 110 万個のオブジェクト数であることが分かります。

default-account-dashboard_-_S3_Storage_Lens_dashboard_1m

以下の 3 つの観点を気にしてみます。

  • リクエストにかかる料金
  • 所要時間
  • 出力結果のファイルサイズ

リクエストにかかる料金

2023年2月時点の東京リージョンのスタンダードクラスの S3 バケットでは、1,000 LIST リクエストあたり 0.0047 USD の料金がかかります。

ひとつの LIST リクエストごとに 1,000 件のオブジェクトを取得できるため、110 万件のオブジェクトを対象にした場合の料金を考えると以下になります。

  • リクエストの回数:
    • 1,100,000(オブジェクト数) / 1,000(1リクエストあたりの取得数) = 1,100 リクエスト
  • リクエストの料金:
    • 0.0047(1,000 リクエストあたりの料金)* 1.1 = 0.00517 USD

ほぼ無視できる範囲の料金であることが分かりました。

所要時間

前後に date コマンドを挟んで実際に計測してみました。

$ date; aws s3 ls cm-chiba-vpc-flowlog --recursive | grep -v '/$' | awk '{print $4}' > result.txt; date               
Mon Feb 27 14:08:41 UTC 2023
Mon Feb 27 14:29:05 UTC 2023

わたしの環境ではおよそ 20 分で実行が完了しました。

AWS CloudShell で実行する場合、20~30分間操作がないとシェルセッションが終了すると仕様があるため注意しましょう。(わたしはコマンドの待機中に適当なキーを打ったりして終了を回避しました。)

出力結果のファイルサイズ

先ほどの出力結果を確認すると 165 MB でした。

$ ls -goh | grep result
-rw-rw-r-- 1 165M Feb 27 14:03 result.txt

AWS CloudShell のストレージは 1GB となっているため、オブジェクト数やオブジェクト名が長い場合には注意が必要そうです。

実行前に大まかなサイズ感を計るには、S3 URI を用いるとよいでしょう。今回対象にしたバケットに格納されていたオブジェクトをひとつピックアップして S3 URI を確認すると、以下の通りです。

s3://cm-chiba-vpc-flowlog/AWSLogs/000000000000/vpcflowlogs/ap-northeast-1/2023/02/27/000000000000_vpcflowlogs_ap-northeast-1_fl-010f7d1bef7c0e169_20230227T0000Z_92fb2273.log.gz

S3://バケット名/を除いたオブジェクト名をカウントすると 150 バイトです。これと同程度のオブジェクト名が 110 万件あるとすると、およそ 165 MB であると試算できます。

出力結果を AWS CloudShell からダウンロードする

AWS CloudShell 上で出力したファイルをローカルの端末にダウンロードできます。(事前にダウンロードしたいファイルのパスを確認しておきましょう。)

「Actions」→「Download file」を押下します。

AWS_CloudShell_Download

ファイルのパスを入力し「Download」を押下します。ホームディレクトリ/home/cloudshell-userは省略できます。

AWS_CloudShell_Download-7508752

↑今回はホームディテクトリ直下にresult.txtを作成していたため、上記の指定でダウンロードができました。

終わりに

AWS CLI で S3 オブジェクトの一覧を出力してみました。

今回は単発で実行できれば良かったので、aws s3 ls での一覧取得で要件にマッチしていました。もう少し定常的に実行が必要、出力結果を他にも活用したい、という場合には S3 インベントリという機能の活用を検討してもよいでしょう。

方式のひとつとして参考になれば幸いです。

以上、 チバユキ (@batchicchi) がお送りしました。

参考