简体   繁体   English

如何使用 python boto3 重命名 s3 文件名

[英]How to rename the s3 file name by using python boto3

Hi i was created a new file/folder in s3 bucket now i want to change the name of the folder/file name.您好,我在 s3 存储桶中创建了一个新文件/文件夹,现在我想更改文件夹/文件名的名称。 how to rename the file/folder name in s3 bucket by using python boto3如何使用 python boto3 重命名 s3 存储桶中的文件/文件夹名称

There is no 'rename' function in Amazon S3. Amazon S3 中没有“重命名”function。 Object names are immutable. Object 名称是不可变的。

You would need to:你需要:

  • Copy the object to a new Key (filename)将 object 复制到新密钥(文件名)
  • Delete the original object删除原来的object

Please note that folders do not actually exist in Amazon S3 .请注意,文件夹实际上并不存在于 Amazon S3中。 Rather, the full path of the object is stored in its Key.相反,object 的完整路径存储在其密钥中。 Thus, it is not possible to rename folders, since that would involve renaming all objects within that path.因此,不可能重命名文件夹,因为这将涉及重命名该路径中的所有对象。 (And objects can't be renamed, as mentioned above.) (并且不能重命名对象,如上所述。)

If you wanted to "rename a folder", you could write a Python script that will:如果你想“重命名文件夹”,你可以编写一个 Python 脚本,它将:

  • Obtain a listing of all objects within the given Prefix获取给定前缀内所有对象的列表
  • Loop through each object, then:循环遍历每个 object,然后:
  • Copy the object to a new Key将 object 复制到一个新的 Key
  • Delete the original object删除原来的object

If you do not want to code this, then there are some tools (eg Cyberduck) that give a nice user interface and can do many of these operations for you.如果您不想为此编写代码,那么可以使用一些工具(例如 Cyberduck)提供漂亮的用户界面,并可以为您完成许多此类操作。

There are a lot of 'issues' with folder structures in s3 it seems as the storage is flat. s3 中的文件夹结构存在很多“问题”,因为存储是平坦的。

I have a Django project where I needed the ability to rename a folder but still keep the directory structure in-tact, meaning empty folders would need to be copied and stored in the renamed directory as well.我有一个 Django 项目,我需要能够重命名文件夹但仍保持目录结构完整,这意味着空文件夹也需要复制并存储在重命名的目录中。

aws cli is great but neither cp or sync or mv copied empty folders (ie files ending in '/') over to the new folder location, so I used a mixture of boto3 and the aws cli to accomplish the task. aws cli很棒,但cpsyncmv都没有将空文件夹(即以“/”结尾的文件)复制到新文件夹位置,因此我混合使用了boto3aws cli来完成任务。

More or less I find all folders in the renamed directory and then use boto3 to put them in the new location, then I cp the data with aws cli and finally remove it.或多或少,我在重命名的目录中找到所有文件夹,然后使用 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