【问题标题】:Amazon S3 boto - how to delete folder?Amazon S3 boto - 如何删除文件夹?
【发布时间】:2012-07-10 17:04:24
【问题描述】:

我在 s3 中创建了一个名为“test”的文件夹,并将“test_1.jpg”、“test_2.jpg”推送到“test”中。

如何使用 boto 删除文件夹“test”?

【问题讨论】:

    标签: python amazon-web-services amazon-s3 boto


    【解决方案1】:

    这里是 2018(几乎是 2019)版本:

    s3 = boto3.resource('s3')
    bucket = s3.Bucket('mybucket')
    bucket.objects.filter(Prefix="myprefix/").delete()
    

    【讨论】:

    • 知道 bucket.objects.all().delete() 清空整个存储桶而不删除它,无论有多少对象(即它不受影响,但 1000 项限制)。见:boto3.amazonaws.com/v1/documentation/api/latest/reference/…
    • 嗨,Raz,这对我不起作用,我只是得到空方括号,即 []
    • 遗憾的是,这不支持后缀:(
    • 最棒的是这个解决方案甚至可以处理超过 1000 个对象
    • 如果您需要指定访问密钥 id 和秘密,第一行是:s3 = boto3.resource('s3', aws_access_key_id=xxx, aws_secret_access_key=yyy)
    【解决方案2】:

    S3 中没有个文件夹。相反,这些键形成了一个平面命名空间。但是,名称中带有斜杠的键会在某些程序中特别显示,包括 AWS 控制台(例如参见 Amazon S3 boto - how to create a folder?)。

    您可以(并且必须)按前缀列出文件并删除,而不是删除“目录”。本质上:

    for key in bucket.list(prefix='your/directory/'):
        key.delete()
    

    但是,此页面上其他已完成的答案具有更有效的方法。


    请注意,前缀只是使用虚拟字符串搜索进行搜索。如果前缀是your/directory,也就是说,没有附加斜杠,程序也会愉快地删除your/directory-that-you-wanted-to-remove-is-definitely-not-t‌​his-one

    欲了解更多信息,请参阅S3 boto list keys sometimes returns directory key.

    【讨论】:

    • 如何删除目录?如果这个目录下的所有文件都被删除了,这个目录是否会被自动删除?
    • @wadehuang - 你能分享你关于删除文件夹的代码吗?
    • 如何在 python 中删除 s3 文件夹中 2 天前的文件。在我的 s3 中有这个 - bucket/1/backups/(10 个文件) 需要删除所有两天前的文件
    【解决方案3】:

    我觉得已经有一段时间了,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 个键,因此您需要多次运行此代码。
    • 如果您有超过 1k 个对象,您可以使用分页器 - 请参阅下面的答案。
    • @deepelement,它只适用于boto3,不适用于boto
    • 这很好用,您可以通过将上面的代码放在 lambda_handler 函数中来从 Python lambda 运行它:import boto3; def lambda_handler(event, context): '''Code from above'''。确保您授予 Lambda 从 S3 中删除并延长超时的权限。
    【解决方案4】:

    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)
    

    【讨论】:

    • 如果您想限制在“目录”中,请使用 paginator.paginate() 中的 Prefix 关键字查看所有选项:boto3.readthedocs.io/en/latest/reference/services/…
    • 使用 @Chad 建议的 Prefix 过滤器,我必须在删除之前添加一个 if item is not None 检查(因为我的一些 S3 前缀不存在/没有对象)
    • @dmitraybelyakov,当我运行上面的代码时,我得到 Typeerror: 'NoneType' object is not scbscriptable on the follwong line delete_us['Objects'].append(dict(key=item['Key '])) 你知道它为什么会这样做
    • @Aaron 也许有些事情已经改变了,但是试试 y2k-shubham 上面的建议
    【解决方案5】:

    您可以将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)
    

    【讨论】:

      【解决方案6】:

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

      s3 = boto3.resource('s3')
      bucket = s3.Bucket('mybucket')
      bucket.object_versions.filter(Prefix="myprefix/").delete()
      

      【讨论】:

      • 有没有办法打印一些正在删除的内容?我想先删除版本,然后再删除当前版本。 ex bucket.objects.filter(Prefix="myprefix/").delete() ;现在我只看到一个闪烁的光标,我不知道发生了什么。
      • 您必须执行files_to_delete = bucket.object_versions.filter(Prefix="myprefix/") 之类的操作,然后遍历files_to_delete 并调用 print() 然后 delete() 。
      【解决方案7】:

      如果需要像我一样按对象内容过滤,以下是您的逻辑蓝图:

      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})
      

      【讨论】:

        猜你喜欢
        • 2010-12-28
        • 2018-11-09
        • 2012-04-07
        • 1970-01-01
        • 2016-01-06
        • 2012-03-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多