在python中使用boto递归地将内容从一个路径复制到另一个s3桶

新手上路,请多包涵

我无法找到任何解决方案来使用 python 中的 boto 在 s3 存储桶中将内容从一个存储桶递归复制到另一个存储桶。

假设 B1 包含的存储桶具有如下键结构: B1/x/* 我想将所有对象从 B/x/* 之类的键递归复制到 B/y/*

原文由 Nitish Agarwal 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 394
2 个回答

S3 中没有“目录”。那些“/”分隔符只是对象名称的一部分,这就是为什么 boto 没有这样的功能。要么写一个脚本来处理它,要么使用第三方工具。

AWS 客户 应用程序展示了提供此类任意目录复制功能的 s3browser 。典型的免费版本只产生两个线程来移动文件,付费版本允许您指定更多线程并运行得更快。

或者你只是编写脚本并使用 s3.client.copy_object 将文件复制到另一个名称,然后删除它们。例如

import boto3
s3 = boto3.client("s3")
# list_objects_v2() give more info

more_objects=True
found_token = True
while more_objects :
  if found_token :
    response= s3.list_objects_v2(
      Bucket="mybucket",
      Prefix="B1/x/",
      Delimiter="/")
  else:
    response= s3.list_objects_v2(
      Bucket="mybucket",
      ContinuationToken=found_token,
      Prefix="B1/x/",
      Delimiter="/")
  # use copy_object or copy_from
  for source in object_list["Contents"]:
    raw_name = source["Key"].split("/")[-1]
    new_name = "new_structure/{}".format(raw_name)
    s3.copy_object(
      ....
    )
    # Now check there is more objects to list
    if "NextContinuationToken" in response:
      found_token = response["NextContinuationToken"]
      more_objects = True
    else:
      more_objects = False

\*\* 重要说明 \*\* :list_object 每个列表最多只返回 1000 个键,MaxKey 不会更改限制。所以你必须使用 list_objects_v2 并检查是否返回 NextContinuationToken ,以确保更多的对象,重复它直到耗尽。

原文由 mootmoot 发布,翻译遵循 CC BY-SA 3.0 许可协议

只是试图建立在以前的答案之上:

 s3 = boto3.client('s3')

def copyFolderFromS3(pathFrom, bucketTo, locationTo):
    response = {}
    response['status'] = 'failed'
    getBucket = pathFrom.split('/')[2]
    location = '/'.join(pathFrom.split('/')[3:])
    if pathFrom.startswith('s3://'):
        copy_source = { 'Bucket': getBucket, 'Key': location }
        uploadKey = locationTo
        recursiveCopyFolderToS3(copy_source,bucketTo,uploadKey)

def recursiveCopyFolderToS3(src,uplB,uplK):
    more_objects=True
    found_token = True
    while more_objects:
        if found_token:
            response = s3.list_objects_v2(
                Bucket=src['Bucket'],
                Prefix=src['Key'],
                Delimiter="/")
        else:
            response = s3.list_objects_v2(
                Bucket=src['Bucket'],
                ContinuationToken=found_token,
                Prefix=src['Key'],
                Delimiter="/")
        for source in response["Contents"]:
            raw_name = source["Key"].split("/")[-1]
            raw_name = raw_name
            new_name = os.path.join(uplK,raw_name)
            if raw_name.endswith('_$folder$'):
                src["Key"] = source["Key"].replace('_$folder$','/')
                new_name = new_name.replace('_$folder$','')
                recursiveCopyFolderToS3(src,uplB,new_name)
            else:
                src['Key'] = source["Key"]
                s3.copy_object(CopySource=src,Bucket=uplB,Key=new_name)
                if "NextContinuationToken" in response:
                    found_token = response["NextContinuationToken"]
                    more_objects = True
                else:
                    more_objects = False

或者您也可以使用默认安装在 EC2/emr 机器上的简单 awscli。

 import subprocess

cmd='aws s3 cp '+path+' '+uploadUrl+' --recursive'
p=subprocess.Popen(cmd, shell=True,stdout=subprocess.PIPE)
p.communicate()

原文由 Suyash Rathi 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题