37

我正在使用 boto 和 python 以及 amazon s3。

如果我使用

[key.name for key in list(self.bucket.list())]

然后我得到所有文件的所有密钥。

mybucket/files/pdf/abc.pdf
mybucket/files/pdf/abc2.pdf
mybucket/files/pdf/abc3.pdf
mybucket/files/pdf/abc4.pdf
mybucket/files/pdf/new/
mybucket/files/pdf/new/abc.pdf
mybucket/files/pdf/2011/

什么是最好的方法

1. either get all folders from s3
2. or from that list just remove the file from the last and get the unique keys of folders

我正在考虑这样做

set([re.sub("/[^/]*$","/",path) for path in mylist]
4

9 回答 9

46

基于sethwm的回答:

要获取顶级目录:

list(bucket.list("", "/"))

要获取 的子目录files

list(bucket.list("files/", "/")

等等。

于 2013-10-17T18:13:31.653 回答
20

正如 j1m 建议的评论方法之一所指出的那样,它返回一个前缀对象。如果您在名称/路径之后,您可以使用变量name。例如:

import boto
import boto.s3

conn = boto.s3.connect_to_region('us-west-2')
bucket = conn.get_bucket(your_bucket)

folders = bucket.list("","/")
for folder in folders:
    print folder.name
于 2015-07-29T14:16:59.363 回答
18

这将是一个不完整的答案,因为我不知道 python 或 boto,但我想评论问题中的基本概念。

其他海报之一是正确的:S3 中没有目录的概念。只有平面键/值对。许多应用程序假装某些分隔符指示目录条目。例如“/”或“\”。有些应用程序甚至会放置一个虚拟文件,以便如果“目录”清空,您仍然可以在列表结果中看到它。

您不必总是将整个存储桶拉下来并在本地进行过滤。S3 有一个分隔列表的概念,您可以在其中指定您认为的路径分隔符(“/”、“\”、“|”、“foobar”等),S3 将向您返回虚拟结果,类似于您的想。

http://docs.aws.amazon.com/AmazonS3/latest/API/RESTBucketGET.html(查看分隔符标头。)

此 API 将为您提供一级目录。因此,如果您在示例中有:

mybucket/files/pdf/abc.pdf
mybucket/files/pdf/abc2.pdf
mybucket/files/pdf/abc3.pdf
mybucket/files/pdf/abc4.pdf
mybucket/files/pdf/new/
mybucket/files/pdf/new/abc.pdf
mybucket/files/pdf/2011/

你传入一个带有前缀“”和分隔符“/”的列表,你会得到结果:

mybucket/files/

如果你传入一个带有前缀“mybucket/files/”和分隔符“/”的列表,你会得到结果:

mybucket/files/pdf/

如果你传入一个带有前缀“mybucket/files/pdf/”和分隔符“/”的列表,你会得到结果:

mybucket/files/pdf/abc.pdf
mybucket/files/pdf/abc2.pdf
mybucket/files/pdf/abc3.pdf
mybucket/files/pdf/abc4.pdf
mybucket/files/pdf/new/
mybucket/files/pdf/2011/

如果您想从结果集中删除 pdf 文件本身,那么您就只能靠自己了。

现在你如何在 python/boto 中做到这一点我不知道。希望有办法通过。

于 2013-07-01T03:36:56.217 回答
11

基本上在 S3 中没有文件夹之类的东西。在内部,所有内容都存储为密钥,如果密钥名称中包含斜线字符,客户端可能会决定将其显示为文件夹。

考虑到这一点,您应该首先获取所有键,然后使用正则表达式过滤掉其中包含斜杠的路径。您现在拥有的解决方案已经是一个好的开始。

于 2013-06-29T08:09:49.843 回答
10

我发现以下使用 boto3 可以工作:

import boto3
def list_folders(s3_client, bucket_name):
    response = s3_client.list_objects_v2(Bucket=bucket_name, Prefix='', Delimiter='/')
    for content in response.get('CommonPrefixes', []):
        yield content.get('Prefix')

s3_client = boto3.client('s3')
folder_list = list_folders(s3_client, bucket_name)
for folder in folder_list:
    print('Folder found: %s' % folder)

参考:

于 2019-06-19T21:24:24.660 回答
7

我看到您已成功建立 boto 连接。如果您只有一个感兴趣的目录(就像您在示例中提供的那样),我认为您可以做的是使用已经通过 AWS ( Link ) 提供的前缀和分隔符。

Boto 在其存储桶对象中使用了此功能,您可以使用前缀和分隔符检索分层目录信息。bucket.list() 将返回一个boto.s3.bucketlistresultset.BucketListResultSet对象。

我尝试了几种方法,如果您确实选择在 中使用delimiter=参数bucket.list(),则返回的对象是 的迭代器boto.s3.prefix.Prefix,而不是boto.s3.key.Key. 换句话说,如果您尝试检索应该放置的子目录delimiter='\',结果,您将获得prefix对象的迭代器

两个返回的对象(前缀或键对象)都有一个.name属性,所以如果你想将目录/文件信息作为一个字符串,你可以通过如下打印来实现:

from boto.s3.connection import S3Connection

key_id = '...'
secret_key = '...'

# Create connection
conn = S3Connection(key_id, secret_key)

# Get list of all buckets
allbuckets = conn.get_all_buckets()
for bucket_name in allbuckets:
    print(bucket_name)

# Connet to a specific bucket
bucket = conn.get_bucket('bucket_name')

# Get subdirectory info
for key in bucket.list(prefix='sub_directory/', delimiter='/'):
    print(key.name)
于 2017-04-06T16:50:03.193 回答
3

正如其他人所说,这里的问题是文件夹不一定有键,因此您必须在字符串中搜索 / 字符并通过它找出您的文件夹。这是生成模仿文件夹结构的递归字典的一种方法。

如果您想要文件夹中的所有文件及其网址

assets = {}
  for key in self.bucket.list(str(self.org) + '/'):
    path = key.name.split('/')

    identifier = assets
  for uri in path[1:-1]:
    try:
      identifier[uri]
    except:
      identifier[uri] = {}
    identifier = identifier[uri]

    if not key.name.endswith('/'):
      identifier[path[-1]] = key.generate_url(expires_in=0, query_auth=False)

return assets

如果你只想要空文件夹

folders = {}
  for key in self.bucket.list(str(self.org) + '/'):
    path = key.name.split('/')

    identifier = folders
  for uri in path[1:-1]:
    try:
      identifier[uri]
    except:
      identifier[uri] = {}
    identifier = identifier[uri]

    if key.name.endswith('/'):
      identifier[path[-1]] = {}

return folders

然后可以在以后递归地读出它。

于 2017-01-20T16:31:41.330 回答
1

boto 接口允许您列出存储桶的内容并给出条目的前缀。这样,您就可以在普通文件系统中获得目录条目:

import boto
AWS_ACCESS_KEY_ID = '...'
AWS_SECRET_ACCESS_KEY = '...'

conn = boto.connect_s3(AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY)
bucket = conn.get_bucket()
bucket_entries = bucket.list(prefix='/path/to/your/directory')

for entry in bucket_entries:
    print entry
于 2013-07-01T04:09:42.963 回答
-1

使用 S3 客户端的 boto3 完整示例

import boto3


def list_bucket_keys(bucket_name):
    s3_client = boto3.client("s3")
    """ :type : pyboto3.s3 """
    result = s3_client.list_objects(Bucket=bucket_name, Prefix="Trails/", Delimiter="/")
    return result['CommonPrefixes']


if __name__ == '__main__':
    print list_bucket_keys("my-s3-bucket-name")
于 2017-11-27T08:55:23.137 回答