【问题标题】:How To Delete S3 Files Starting With如何删除 S3 文件开头
【发布时间】:2014-03-19 21:55:06
【问题描述】:

假设我在 S3 上有不同尺寸的图像:

137ff24f-02c9-4656-9d77-5e761d76a273.webp
137ff24f-02c9-4656-9d77-5e761d76a273_500_300.webp
137ff24f-02c9-4656-9d77-5e761d76a273_400_280.webp

我正在使用 boto 删除单个文件:

bucket = get_s3_bucket()
s3_key = Key(bucket)
s3_key.key = '137ff24f-02c9-4656-9d77-5e761d76a273.webp'
bucket.delete_key(s3_key)

但我想删除所有以 137ff24f-02c9-4656-9d77-5e761d76a273 开头的键。

请记住,存储桶中可能有数百个文件,因此我不想遍历所有文件。有没有办法只删除以某个字符串开头的文件?

也许是一些正则表达式删除功能。

【问题讨论】:

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


    【解决方案1】:

    S3 服务支持多重删除操作,允许您在单个 API 调用中删除多达 1000 个对象。但是,此 API 调用不支持密钥的服务器端过滤。您必须提供要删除的键列表。

    您可以自己滚动。首先,您需要获取要删除的所有键的列表。

    import boto
    
    s3 = boto.connect_s3()
    bucket = s3.get_bucket('mybucket')
    to_delete = list(bucket.list(prefix='137ff24f-02c9-4656-9d77-5e761d76a273'))
    

    list 调用返回一个生成器,但我正在使用 list 将其转换为列表,因此,to_delete 变量现在指向存储桶中与我提供的前缀匹配的所有对象的列表.

    现在,我们需要从大列表中创建最多 1000 个对象的块,并使用该块调用存储桶对象的 delete_keys 方法。

    for chunk in [to_delete[i:i+1000] for i in range(0, len(to_delete), 1000)]:
        result = bucket.delete_keys(chunk)
        if result.errors:
            print('The following errors occurred')
            for error in result.errors:
                print(error)
    

    有更有效的方法可以做到这一点(例如,不将存储桶生成器转换为列表),您可能希望在处理错误时做一些不同的事情,但这应该会给您一个开始。

    【讨论】:

      【解决方案2】:

      您可以使用 aws cli:https://aws.amazon.com/cli/ 和一些 unix 命令来完成。

      这个 aws cli 命令应该可以工作:

      aws s3 rm <your_bucket_name> --exclude "*" --include "*137ff24f-02c9-4656-9d77-5e761d76a273*" 
      

      如果你想包含子文件夹,你应该添加标志 --recursive

      或使用 unix 命令:

      aws s3 ls s3://<your_bucket_name>/ | awk '{print $4}' | xargs -I%  <your_os_shell>   -c 'aws s3 rm s3:// <your_bucket_name>  /% $1'
      

      解释: 列出存储桶上的所有文件 --pipe--> 获取第四个参数(文件名)--pipe--> 使用 aws cli 运行删除脚本

      【讨论】:

        【解决方案3】:

        是的。尝试使用s3cmd,S3 的命令行工具。首先获取bucket中所有文件的列表。

        cmd = 's3cmd ls s3://bucket_name'
        args = shlex.split(cmd)
        ls_lines = subprocess.check_output(args).splitlines()
        

        然后找到所有以您想要的字符串开头的行(使用正则表达式,应该很简单)。使用命令删除所有thrm:

        s3cmd del s3://bucket_name/file_name(s)
        

        或者,如果您只想使用单个命令:

        s3cmd del s3://bucket_name/string*
        

        我提到了第一种方法,以便您可以测试要删除的文件的名称,而不会意外删除其他任何内容。

        【讨论】:

        • 使用 asterix (*) 的通配符删除绝对有效 s3://bucket-name/string*!!!!!!!!
        • 但是,在后台 s3cmd 似乎会一个一个地删除文件(在我的情况下,每个文件大约需要 0.5 秒)。因此,如果您需要快速删除半百万个文件,那么您将需要基于多重删除的解决方案。但是对于 S3 存储桶的偶尔清洁,这种方法似乎非常好
        【解决方案4】:

        对于 boto3,以下 sn-p 删除所有以特定前缀开头的文件:

        import boto3
        
        botoSession = boto3.Session(
            aws_access_key_id     = <your access key>,
            aws_secret_access_key = <your secret key>,
            region_name           = <your region>,
        )
        
        s3 = botoSession.resource('s3')
        bucket = s3.Bucket(bucketname)
        objects = bucket.objects.filter(Prefix=<your prefix>)
        objects.delete()
        

        【讨论】:

          【解决方案5】:

          虽然没有直接的 boto 方法来做你想做的事,但你应该能够通过使用 get_all_keys、使用上述正则表达式过滤它们,然后调用 delete_keys 来有效地做到这一点。

          这样做只会使用两个请求,并且在客户端执行正则表达式应该非常快

          【讨论】:

            猜你喜欢
            • 2020-10-31
            • 1970-01-01
            • 2011-03-16
            • 2020-09-28
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多