【问题标题】:Is there a simple way to rename s3 folder via boto3?有没有一种简单的方法可以通过 boto3 重命名 s3 文件夹?
【发布时间】:2021-10-16 03:36:07
【问题描述】:

我有带文件夹的 s3 存储桶,文件夹内有大文件。

我想用 python3-boto3 脚本重命名文件夹。

我阅读了this(“如何使用 Python 重命名 Amazon S3 文件夹对象”),他正在做的是复制带有新前缀的文件,然后删除原始文件夹。

这样做效率很低,而且因为我的文件很大,所以需要很长时间。

有没有更简单/更有效的方法?

【问题讨论】:

标签: amazon-web-services amazon-s3 boto3


【解决方案1】:

无法重命名 s3 对象/文件夹 - 您需要将它们复制到新名称并删除旧名称。

在 aws cli 中有一个 mv 命令,但在幕后它正在为您复制然后删除 - 这样您可以使操作更容易,但这不是真正的“重命名” '。

https://docs.aws.amazon.com/cli/latest/reference/s3/mv.html

【讨论】:

    【解决方案2】:

    简单,不。很遗憾。

    s3 中的文件夹结构存在很多“问题”,因为存储空间是扁平的。

    我有一个 Django 项目,我需要能够重命名文件夹但仍保持目录结构完整,这意味着空文件夹也需要复制并存储在重命名的目录中。

    aws cli 很棒,但 cpsyncmv 都没有将空文件夹(即以“/”结尾的文件)复制到新文件夹位置,所以我混合使用了 boto3aws cli 完成任务。

    我或多或少找到重命名目录中的所有文件夹,然后使用boto3将它们放在新位置,然后我cpaws cli的数据,最后将其删除。

    import threading
    
    import os
    from django.conf import settings
    from django.contrib import messages
    from django.core.files.storage import default_storage
    from django.shortcuts import redirect
    from django.urls import reverse
    
    def rename_folder(request, client_url):
        """
        :param request:
        :param client_url:
        :return:
        """
        current_property = request.session.get('property')
        if request.POST:
            # name the change
            new_name = request.POST['name']
            # old full path with www.[].com?
            old_path = request.POST['old_path']
            # remove the query string
            old_path = ''.join(old_path.split('?')[0])
            # remove the .com prefix item so we have the path in the storage
            old_path = ''.join(old_path.split('.com/')[-1])
            # remove empty values, this will happen at end due to these being folders
            old_path_list = [x for x in old_path.split('/') if x != '']
    
            # remove the last folder element with split()
            base_path = '/'.join(old_path_list[:-1])
            # # now build the new path
            new_path = base_path + f'/{new_name}/'
            # remove empty variables
            # print(old_path_list[:-1], old_path.split('/'), old_path, base_path, new_path)
            endpoint = settings.AWS_S3_ENDPOINT_URL
            # # recursively add the files
            copy_command = f"aws s3 --endpoint={endpoint} cp s3://{old_path} s3://{new_path} --recursive"
            remove_command = f"aws s3 --endpoint={endpoint} rm s3://{old_path} --recursive"
            
            # get_creds() is nothing special it simply returns the elements needed via boto3
            client, resource, bucket, resource_bucket = get_creds()
            path_viewing = f'{"/".join(old_path.split("/")[1:])}'
            directory_content = default_storage.listdir(path_viewing)
    
            # loop over folders and add them by default, aws cli does not copy empty ones
            # so this is used to accommodate
            folders, files = directory_content
            for folder in folders:
                new_key = new_path+folder+'/'
                # we must remove bucket name for this to work
                new_key = new_key.split(f"{bucket}/")[-1]
                # push this to new thread
                threading.Thread(target=put_object, args=(client, bucket, new_key,)).start()
                print(f'{new_key} added')
    
            # # run command, which will copy all data
            os.system(copy_command)
            print('Copy Done...')
            os.system(remove_command)
            print('Remove Done...')
    
            # print(bucket)
            print(f'Folder renamed.')
            messages.success(request, f'Folder Renamed to: {new_name}')
    
        return redirect(request.META.get('HTTP_REFERER', f"{reverse('home', args=[client_url])}"))
    
    

    【讨论】:

      猜你喜欢
      • 2016-09-24
      • 1970-01-01
      • 2015-05-12
      • 2023-03-06
      • 2011-06-03
      • 2011-03-20
      • 2015-04-17
      • 1970-01-01
      • 2020-10-04
      相关资源
      最近更新 更多