いろいろハマったのでメモ
- ファイル情報を1回で取れない
- 一度に1000個まで
- Lambdaの15分制限を超えた
- S3にフォルダはない
あるフォルダ以下のファイル一覧をCSVで出力
Lambdaのログでは行数に制限があるのでCSVで保存します。
拡張子 mp4 のみを検索します。
ファイル名、ファイルサイズ、更新日時も出力します。
S3Bucket = 'bucket'
S3KeyPrefix = 'folder/'
s3 = boto3.resource('s3')
bucket = s3.Bucket(S3Bucket)
objs = bucket.meta.client.list_objects_v2(Bucket=bucket.name, Prefix=S3KeyPrefix)
csv = '{},{},{}\n'.format('file', 'size_mb', 'date')
for o in objs.get('Contents'):
key = o.get('Key')
size = o.get('Size')
date = o.get('LastModified')
if key[-4:]=='.mp4':
csv += '{},{},{}\n'.format(key, int(size/1024/1024), date.strftime("%Y-%m-%d %H:%M:%S"))
s3_resource = boto3.resource('s3')
s3_resource.Object(S3Bucket, 'file_list.csv').put(Body=csv)
S3のフォルダ一覧(ファイル数、サイズ、更新日時付き)
S3のフォルダ一覧を出力します。
サブフォルダは含みません。
フォルダ名、ファイル数、サイズ、一番新しい更新日時を出力します。
S3Bucket = 'bucket'
S3KeyPrefix = 'folder/'
s3 = boto3.resource('s3')
bucket = s3.Bucket(S3Bucket)
objs = bucket.meta.client.list_objects(Bucket=bucket.name, Prefix=S3KeyPrefix, Delimiter='/')
csv = '{},{},{},{}\n'.format('folder', 'count', 'size_mb', 'date')
for o in objs.get('CommonPrefixes'):
folder = o.get('Prefix')
files = bucket.meta.client.list_objects_v2(Bucket=bucket.name, Prefix=folder)
total_size = 0
file_count = 0
last_date = datetime(2000, 1, 1)
for f in files.get('Contents'):
if f.get('Key')[-1:]!="/":
total_size += f.get('Size')
file_count += 1
date = datetime.strptime(f.get('LastModified').strftime("%Y-%m-%d"), "%Y-%m-%d")
if last_date<date:
last_date=date
csv += '{},{},{},{}\n'.format(folder, file_count, int(total_size/1024/1024), last_date.strftime("%Y-%m-%d"))
s3_resource = boto3.resource('s3')
s3_resource.Object(S3Bucket, 'folder_list.csv').put(Body=csv)
S3のフォルダ一覧(1000個以上に対応)
list_objectsは上限1000個のため、objects.all()を使用します。
2階層(/2本)までを切り取りリストに追加します。
lambda.py
from boto3 import Session
S3Bucket = 'bucket'
S3KeyPrefix = 'folder/'
folder_list = []
sbucket = Session().resource('s3').Bucket(S3Bucket)
keys = [obj.key for obj in sbucket.objects.all()]
for k in keys:
ks = k.split('/')
if len(ks)>=2:
k2 = ks[0] +'/'+ ks[1]+'/'
if (k2 in folder_list) == False:
folder_list.append(k2)
S3のフォルダ一覧(1000個以上、Lambda15分制限に対応)
ファイル数が多いと上記のobjects.all()ではlambdaの最大の15分を超えました。
以下のコードでは、folder/a...検索、folder/b...検索を繰り返します。
大文字Aは不可です。a以下が1000個の場合は不可です。
preList = ['0','1','2','3','4','5','6','7','8','9','0']
preList += ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z']
folder_list = []
for pre in preList:
objs = bucket.meta.client.list_objects_v2(
Bucket=S3Bucket,
Prefix=S3KeyPrefix + pre,
Delimiter='/'
)
if objs.get('CommonPrefixes') is None:
continue
for o in objs.get('CommonPrefixes'):
folder_list.append(o.get('Prefix'))
まとめ
3年くらい実運用で使っているS3で、不要データを削除するスクリプトを作ることになりました。削除といっても保険として、Trashフォルダに移動(コピー&削除)をします。削除の前段で、ファイルやフォルダ、サイズ、日時をリスト化することから始めました。まさか一覧取得に15分もかかるとは思いませんでした。やはり本番環境は色々なことが起きます。