亚马逊S3 boto - 如何删除文件夹?

wad*_*ang 53 python amazon-s3 boto

我在s3中创建了一个名为"test"的文件夹,然后将"test_1.jpg","test_2.jpg"推入"test".

现在我想用boto删除文件夹"test".

我该怎么办?

Raz*_*Raz 83

这是2018年(差不多2019年)版本:

s3 = boto3.resource('s3')
bucket = s3.Bucket('mybucket')
bucket.objects.filter(Prefix="myprefix/").delete()
Run Code Online (Sandbox Code Playgroud)

  • 到目前为止,这是最好的答案。 (9认同)
  • 很棒的是,这个解决方案甚至可以处理 1000 多个对象 (5认同)
  • 嗨,拉兹,这对我不起作用,我只是得到空方括号,即 [] (3认同)
  • 有人可能会发现,无论有多少对象,bucket.objects.all().delete() 都会清空整个存储桶而不删除它,这很有用(即它不受影响,但有 1000 个项目的限制)。请参阅:https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/s3.html#S3.Bucket.objects (2认同)

Ant*_*ala 49

S3 中没有文件夹.相反,键形成一个平面命名空间.但是,名称中带有斜杠的键会在某些程序中特别显示,包括AWS控制台(请参阅Amazon S3 boto - 如何创建文件夹?).

您可以(并且必须)通过前缀和删除列出文件,而不是删除"目录".在本质上:

for key in bucket.list(prefix='your/directory/'):
    key.delete()
Run Code Online (Sandbox Code Playgroud)

然而,此页面上其他完成的答案具有更有效的方法.


请注意,只使用虚拟字符串搜索来搜索前缀.如果前缀是your/directory,即没有附加尾部斜杠,程序也会愉快地删除your/directory-that-you-wanted-to-remove-is-definitely-not-t??his-one.

有关更多信息,请参阅S3 boto列表键有时会返回目录键.


Pat*_*ick 41

我觉得已经有一段时间了,boto3有几种不同的方式来实现这个目标.这假设您要删除测试 "文件夹"及其所有对象以下是一种方法:

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)
Run Code Online (Sandbox Code Playgroud)

这应该产生两个请求,一个用于获取文件夹中的对象,第二个用于删除所述文件夹中的所有对象.

https://boto3.readthedocs.org/en/latest/reference/services/s3.html#S3.Client.delete_objects

  • 如果你有超过1k个对象,你可以使用paginator - 请参阅下面的答案. (4认同)
  • 这是最快的解决方案,但请记住,`list_objects` 不能返回超过 1000 个键,因此您需要多次运行此代码。 (2认同)
  • 这非常有效,您可以通过将上面的代码放入 lambda_handler 函数中来从 Python lambda 运行它:def lambda_handler(event, context): '''上面的代码'''`。确保您授予 Lambda 从 S3 删除并延长超时的权限。 (2认同)

Dav*_*oks 19

你可以使用带有键列表的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)
Run Code Online (Sandbox Code Playgroud)


dmi*_*kov 18

Patrick的解决方案略有改进.正如你可能知道,无论是list_objects()delete_objects()有1000的对象限制这就是为什么你必须进行分页上市和块删除.这是非常普遍的,你可以给Prefixpaginator.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)
Run Code Online (Sandbox Code Playgroud)

  • 如果你想限制为"目录",请使用`paginator.paginate()中的`Prefix`关键字.查看所有选项:http://boto3.readthedocs.io/en/latest/reference/services/s3.html #S3.Paginator.ListObjectsV2.paginate (2认同)
  • 使用 **@Chad** 建议的“Prefix”过滤器,我必须在删除之前添加“if item is not None”检查(因为我的一些 S3 前缀不存在/没有对象) (2认同)

Dan*_*Dev 9

如果在 S3 存储桶上启用了版本控制:

s3 = boto3.resource('s3')
bucket = s3.Bucket('mybucket')
bucket.object_versions.filter(Prefix="myprefix/").delete()
Run Code Online (Sandbox Code Playgroud)