s3に「test」という名前のフォルダーを作成し、「test_1.jpg」、「test_2.jpg」を「test」にプッシュしました。
botoを使用してフォルダ「test」を削除するにはどうすればよいですか?
回答:
S3にはフォルダはありません。代わりに、キーはフラットな名前空間を形成します。ただし、名前にスラッシュが含まれるキーは、AWSコンソールなどの一部のプログラムで特に表示されます(たとえば、Amazon S3 boto-フォルダーの作成方法を参照してください)。
「ディレクトリ」を削除する代わりに、プレフィックスと削除でファイルを一覧表示できます(そして削除する必要があります)。本質的に:
for key in bucket.list(prefix='your/directory/'):
key.delete()
ただし、このページの他の達成された回答は、より効率的なアプローチを特徴としています。
プレフィックスはダミー文字列検索を使用して検索されることに注意してください。プレフィックスがだった場合、つまり末尾にスラッシュが追加されていない場合、プログラムは喜んで削除しyour/directory
your/directory-that-you-wanted-to-remove-is-definitely-not-this-one
ます。
詳細については、S3を参照してください。botoリストキーがディレクトリキーを返す場合があります。
これが2018(ほぼ2019)バージョンです:
s3 = boto3.resource('s3')
bucket = s3.Bucket('mybucket')
bucket.objects.filter(Prefix="myprefix/").delete()
久しぶりだと思いますが、boto3にはこの目標を達成するためのいくつかの異なる方法があります。これは、テスト「フォルダー」とそのすべてのオブジェクトを削除することを前提としています。これは1つの方法です。
s3 = boto3.resource('s3')
objects_to_delete = s3.meta.client.list_objects(Bucket="MyBucket", Prefix="myfolder/test/")
delete_keys = {'Objects' : []}
delete_keys['Objects'] = [{'Key' : k} for k in [obj['Key'] for obj in objects_to_delete.get('Contents', [])]]
s3.meta.client.delete_objects(Bucket="MyBucket", Delete=delete_keys)
これにより、2つの要求が行われる必要があります。1つはフォルダー内のオブジェクトをフェッチし、もう1つはそのフォルダー内のすべてのオブジェクトを削除するためです。
https://boto3.readthedocs.org/en/latest/reference/services/s3.html#S3.Client.delete_objects
list_objects
、1000を超えるキーを返すことはできないため、このコードを複数回実行する必要があることに注意してください。
boto3
はボトではなく、でのみ機能します
import boto3; def lambda_handler(event, context): '''Code from above'''
。LambdaにS3から削除してタイムアウトを延長する許可を与えていることを確認してください。
キーのリストでbucket.delete_keys()を使用できます(キーの数が多いと、key.deleteを使用するよりも1桁高速であることがわかりました)。
このようなもの:
delete_key_list = []
for key in bucket.list(prefix='/your/directory/'):
delete_key_list.append(key)
if len(delete_key_list) > 100:
bucket.delete_keys(delete_key_list)
delete_key_list = []
if len(delete_key_list) > 0:
bucket.delete_keys(delete_key_list)
パトリックのソリューションのわずかな改善。あなたが知っている、両方のかもしれませんがlist_objects()
とdelete_objects()
1000のオブジェクトの制限を持っているあなたはリストページ付けとチャンクで削除する必要が理由です。これはかなり普遍的であり、あなたが与えることができますPrefix
にpaginator.paginate()
削除サブディレクトリ/パスに
client = boto3.client('s3', **credentials)
paginator = client.get_paginator('list_objects_v2')
pages = paginator.paginate(Bucket=self.bucket_name)
delete_us = dict(Objects=[])
for item in pages.search('Contents'):
delete_us['Objects'].append(dict(Key=item['Key']))
# flush once aws limit reached
if len(delete_us['Objects']) >= 1000:
client.delete_objects(Bucket=bucket, Delete=delete_us)
delete_us = dict(Objects=[])
# flush rest
if len(delete_us['Objects']):
client.delete_objects(Bucket=bucket, Delete=delete_us)
Prefix
にキーワードをpaginator.paginate()
参照してくださいすべてのオプション:boto3.readthedocs.io/en/latest/reference/services/...を
Prefix
提案されたフィルタ@Chad、私は追加する必要がありましたif item is not None
削除前のチェックを(私のS3プレフィックスの一部が存在していなかったので、/何のオブジェクトがありませんでした)
S3バケットでバージョン管理が有効になっている場合:
s3 = boto3.resource('s3')
bucket = s3.Bucket('mybucket')
bucket.object_versions.filter(Prefix="myprefix/").delete()
files_to_delete = bucket.object_versions.filter(Prefix="myprefix/")
次に、繰り返してfiles_to_delete
print()を呼び出し、次にdelete()を呼び出すなどの操作を行う必要があります。
私が行ったようにオブジェクトの内容でフィルタリングする必要がある場合、以下はロジックの青写真です。
def get_s3_objects_batches(s3: S3Client, **base_kwargs):
kwargs = dict(MaxKeys=1000, **base_kwargs)
while True:
response = s3.list_objects_v2(**kwargs)
# to yield each and every file: yield from response.get('Contents', [])
yield response.get('Contents', [])
if not response.get('IsTruncated'): # At the end of the list?
break
continuation_token = response.get('NextContinuationToken')
kwargs['ContinuationToken'] = continuation_token
def your_filter(b):
raise NotImplementedError()
session = boto3.session.Session(profile_name=profile_name)
s3client = session.client('s3')
for batch in get_s3_objects_batches(s3client, Bucket=bucket_name, Prefix=prefix):
to_delete = [{'Key': obj['Key']} for obj in batch if your_filter(obj)]
if to_delete:
s3client.delete_objects(Bucket=bucket_name, Delete={'Objects': to_delete})