AWS CLIを使ってS3オブジェクトを抽出する色んな方法

こんにちは福崎です! S3にバックアップ的にロストしたくない情報を保存しており、障害発生時とかたまに検索するんですが、aws console上ではprefixでしか絞れないので、最終更新日で絞ったりソートするのどうやるんだってメモ。

日付で絞る

LastModifiedの範囲を指定。

aws s3api list-objects 
  --bucket my_bucket 
  --prefix my_prefix
  --query 'Contents[?LastModified >= `2019-01-07` && LastModified <= `2019-01-08`]' 

日時で絞る

UTCでの絞り込みになるので注意。

aws s3api list-objects 
  --bucket my_bucket 
  --prefix my_prefix
  --query 'Contents[?LastModified >= `2019-01-07T00:00:00` && LastModified <= `2019-01-08T23:59:59`]' 

絞り込んだものを昇順でソートする

aws s3api list-objects 
  --bucket my_bucket 
  --prefix my_prefix
  --query 'Contents[?LastModified >= `2019-01-07T00:00:00` && LastModified <= `2019-01-08T23:59:59`] | sort_by(@, &LastModified)' 

最大のものを抽出する

aws s3api list-objects 
  --bucket my_bucket 
  --prefix my_prefix
  --query 'Contents[?LastModified >= `2019-01-07T00:00:00` && LastModified <= `2019-01-08T23:59:59`] | max_by(@, &LastModified)' 

注意

query部分の処理はクライアント側で実行されます。なので大きいbucketに対して実行すると時間がかかるし料金も発生するので注意です。 https://aws.amazon.com/jp/s3/pricing/

そのへんの議論と、サーバー側でフィルタリングする機能を実装してくれという話はここで行われています。 +1していくともしかしたら実装されるかもという儚い願いを込めて、自分も+1しておきました。 https://github.com/aws/aws-cli/issues/1104

query部分の記法について

query部分ってあまり見慣れない記法で書かれていますが、JMESPathというjsonをクエリする言語で書かれているようです。 s3に限らずAWS CLIのqueryオプションで使うことが出来るようなので、覚えておくと他でも活用できそうです。

チュートリアルはこちら。 http://jmespath.org/tutorial.html

ここで試せます。 http://jmespath.org/

簡単な解説

s3api list-objects はこういうjsonを返してきます。

{
    "Contents": [
        {
            "Key": "my_prefix",
            "LastModified": "2019-01-07T02:42:17.000Z",
            "ETag": "\"11111111111111111111\"",
            "Size": 12744,
            "StorageClass": "STANDARD",
            "Owner": {
                "DisplayName": "aaaaaaaaaaaaaaaaaaaaaa",
                "ID": "1111111111111111111111111111"
            }
        }
   ]
}

Contentsの下に配列でLastModifiedというキーがあるobject群が返ってくるので、それに対してqueryを書いて上げると絞り込みができます。

Contents[?LastModified >= `2019-01-07T00:00:00` && LastModified <= `2019-01-08T23:59:59`]

他にもどのキーを抽出するかを指定することが出来たり、

Contents[?LastModified >= `2019-01-07T00:00:00` && LastModified <= `2019-01-08T23:59:59`].[Key]

#=>
[
  [
     "key1"
  ],
  [
     "key2"
  ]
]

built-in関数を使うことも出来ます。 built-in関数はこの辺りにまとまってます。 http://jmespath.org/specification.html#functions

Contents[?LastModified >= `2019-01-07T00:00:00` && LastModified <= `2019-01-08T23:59:59`].[length(Key)]

#=>
[
  [
     12
  ],
  [
     13
  ]
]