import boto3 def pull_s3_prefix(dst_dir, bucket, prefix): client = boto3.client('s3') resource = boto3.resource('s3') download_dir(client, resource, prefix, prefix, dst_dir, bucket) def download_dir(client, resource, prefix, start_prefix, local, bucket ): paginator = client.get_paginator('list_objects') for result in paginator.paginate(Bucket=bucket, Delimiter='/', Prefix=prefix): if result.get('CommonPrefixes') is not None: for subdir in result.get('CommonPrefixes'): download_dir(client, resource, subdir.get('Prefix'), start_prefix, local, bucket) if result.get('Contents') is not None: for file in result.get('Contents'): key_relative = file.get('Key').replace(start_prefix, '') if not os.path.exists(os.path.dirname(local + os.sep + key_relative)): os.makedirs(os.path.dirname(local + os.sep + key_relative)) local_path = local + os.sep + key_relative s3_path = file.get('Key') print(f"Downloading {s3_path} -> {local_path}") resource.meta.client.download_file(bucket, s3_path, local_path) def upload_dir_s3(source_dir, dst_bucket, dst_prefix=''): client = boto3.client('s3') # enumerate local files recursively for root, dirs, files in os.walk(source_dir): for filename in files: # construct the full local path local_path = os.path.join(root, filename) # construct the full Dropbox path relative_path = os.path.relpath(local_path, source_dir) s3_path = os.path.join(dst_prefix, relative_path) # s3_path = "{dst_prefix}{s3_path}" # relative_path = os.path.relpath(os.path.join(root, filename)) try: print("Uploading %s..." % s3_path) client.upload_file(local_path, dst_bucket, s3_path) # try: # client.delete_object(Bucket=bucket, Key=s3_path) # except: # print "Unable to delete %s..." % s3_path except Exception as e: logger.exception(f"Failed to upload {local_path} to {s3_path}")