【发布时间】:2012-07-10 17:04:24
【问题描述】:
我在 s3 中创建了一个名为“test”的文件夹,并将“test_1.jpg”、“test_2.jpg”推送到“test”中。
如何使用 boto 删除文件夹“test”?
【问题讨论】:
标签: python amazon-web-services amazon-s3 boto
我在 s3 中创建了一个名为“test”的文件夹,并将“test_1.jpg”、“test_2.jpg”推送到“test”中。
如何使用 boto 删除文件夹“test”?
【问题讨论】:
标签: python amazon-web-services amazon-s3 boto
这里是 2018(几乎是 2019)版本:
s3 = boto3.resource('s3')
bucket = s3.Bucket('mybucket')
bucket.objects.filter(Prefix="myprefix/").delete()
【讨论】:
S3 中没有个文件夹。相反,这些键形成了一个平面命名空间。但是,名称中带有斜杠的键会在某些程序中特别显示,包括 AWS 控制台(例如参见 Amazon S3 boto - how to create a folder?)。
您可以(并且必须)按前缀列出文件并删除,而不是删除“目录”。本质上:
for key in bucket.list(prefix='your/directory/'):
key.delete()
但是,此页面上其他已完成的答案具有更有效的方法。
请注意,前缀只是使用虚拟字符串搜索进行搜索。如果前缀是,也就是说,没有附加斜杠,程序也会愉快地删除your/directoryyour/directory-that-you-wanted-to-remove-is-definitely-not-this-one。
欲了解更多信息,请参阅S3 boto list keys sometimes returns directory key.
【讨论】:
我觉得已经有一段时间了,boto3 有几种不同的方式来实现这个目标。这假设您要删除 test “文件夹”及其所有对象这是一种方法:
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)
这应该发出两个请求,一个是获取文件夹中的对象,第二个是删除所述文件夹中的所有对象。
https://boto3.readthedocs.org/en/latest/reference/services/s3.html#S3.Client.delete_objects
【讨论】:
list_objects 不能返回超过 1000 个键,因此您需要多次运行此代码。
boto3,不适用于boto
import boto3; def lambda_handler(event, context): '''Code from above'''。确保您授予 Lambda 从 S3 中删除并延长超时的权限。
Patrick 的解决方案略有改进。您可能知道,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)
【讨论】:
paginator.paginate() 中的 Prefix 关键字查看所有选项:boto3.readthedocs.io/en/latest/reference/services/…
Prefix 过滤器,我必须在删除之前添加一个 if item is not None 检查(因为我的一些 S3 前缀不存在/没有对象)
您可以将bucket.delete_keys() 与键列表一起使用(对于大量键,我发现这比使用 key.delete 快一个数量级)。
类似这样的:
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)
【讨论】:
如果在 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})
【讨论】: