@57105710hk

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

PythonでAWS S3のバケット内の古いファイルを削除したい

解決したいこと

現在Lambdaで開発を行っています。
PythonでS3のバケット内の古いファイルを削除したいです。

処理手順は以下を考えております。
1.S3のバケットを指定
2.特定の拡張子(zip)のファイルの更新日時・ファイル名を取得
3.ファイルを更新日時順にソート
4.更新日時が古いものから削除し、ファイル数を1にする

発生している問題・エラー

・実施できたこと
 ・バケット内のすべてのファイルを取得
・実施できていないこと
 ・特定の拡張子に限定した取得
 ・更新日時の取得・ソート
 ・更新日時の古いものから削除し、ファイル数を1にする

自分で試したこと

言語名 Python

import boto3
import os
 
Bucket = os.getenv('S3のバケット')
 
def lambda_handler(event, context):
    client = boto3.client('s3')
    obj = client.list_objects(Bucket=Bucket)
    print([content['Key'] for content in obj['Contents']])
    print(obj)
    
0 likes

2Answer

特定の拡張子に限定した取得

S3のlist_objects_v2オペレーションではダウンロード対象のフィルタリングはPrefixを用いた前方一致のみ可能で、中間一致や後方一致はできません。
そのため、拡張子で絞り込んでダウンロードする場合には、ファイル保存時にオブジェクトのキーを /.../zip/file.zip などのようにprefixで拡張子を絞り込めるようにしておく必要があります。

ただし、ダウンロード後にプログラム内で絞り込みすることは可能で、例えば

result = client.list_objects(Bucket=Bucket)
objects = result['Contents']
zip_objects = [obj for obj in  objects if obj['Key'].endswith('.zip')]

などと書くことができます。
あくまでローカルでの絞り込みですので、例えばバケットに全部で1000件あってzipが1件の場合、1000件ともダウンロードしてから1件だけzip_objectsに代入する、という挙動になるので十分ご注意ください

更新日時の取得・ソート

result = client.list_objects(Bucket=Bucket)
objects = result['Contents']

# 先頭のオブジェクトの更新日時
last_modified = objects[0]['LastModified']

# 更新日時(古い順)でソートしたオブジェクトのlist
oldest_objects = sorted(objects, key= lambda obj: obj['LastModified'])

などと書くことができます

更新日時の古いものから削除し、ファイル数を1にする

result = client.list_objects(Bucket=Bucket)
objects = result['Contents']

# 更新日時(古い順)でソートしたオブジェクトのlist
oldest_objects = sorted(objects, key=lambda obj: obj['LastModified'])

# 削除対象のオブジェクト
target_objects = oldest_objects[:-1]

# 削除
client.delete_objects(
    Bucket=Bucket,
    Delete={
        'Objects': [{'Key': obj['Key']} for obj in target_objects]
    }
)

などと書くことができます
https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/s3.html#S3.Client.delete_objects

補足

  1. list_objectsは古いバージョンのメソッドで、不具合があるわけではありませんが現在非推奨となっていますので、list_objects_v2を使うことにも是非挑戦してみてください
  2. boto3には高レベルAPIと呼ばれるメソッドもあり、今回のケースであればそちらを使ったほうが扱いやすいかもしれません。こちらも余裕があればぜひ挑戦してみてください。
0Like

ご回答ありがとうございます。
とても分かりやすい説明で、実施したい内容について無事にできました。
ありがとうございました。

0Like

Your answer might help someone💌