繁体   English   中英

有没有一种简单的方法可以通过 boto3 重命名 s3 文件夹?

[英]Is there a simple way to rename s3 folder via boto3?

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

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

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

这是非常低效的方法,而且因为我有大文件,所以需要很长时间才能完成。

有没有更简单/更有效的方法来做到这一点?

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

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

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

很简单,不。 很遗憾。

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

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

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM