[英]Is there a simple way to rename s3 folder via boto3?
我有带文件夹的 s3 存储桶,文件夹内有大文件。
我想用 python3-boto3 脚本重命名文件夹。
我读了这篇文章(“如何使用 Python 重命名 Amazon S3 文件夹对象”),他所做的是复制具有新前缀的文件,然后删除原始文件夹。
这是非常低效的方法,而且因为我有大文件,所以需要很长时间才能完成。
有没有更简单/更有效的方法来做到这一点?
无法重命名 s3 对象/文件夹 - 您需要将它们复制到新名称并不幸地删除旧名称。
aws cli 中有一个mv命令,但在幕后它正在为您复制然后删除 - 这样您可以使操作更容易,但这不是真正的“重命名”。
很简单,不。 很遗憾。
s3 中的文件夹结构存在很多“问题”,因为存储是平坦的。
我有一个 Django 项目,我需要能够重命名文件夹但仍保持目录结构完整,这意味着空文件夹也需要复制并存储在重命名的目录中。
aws cli
很棒,但cp
或sync
或mv
都没有将空文件夹(即以“/”结尾的文件)复制到新文件夹位置,因此我混合使用了boto3
和aws 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.