如何使用python boto获得AmazonS3中仅有的文件夹列表?

如何使用python boto获得AmazonS3中仅有的文件夹列表?,python,amazon-s3,boto,Python,Amazon S3,Boto,我正在使用boto、python和amazons3 如果我使用 [输入列表的key.name(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 m

我正在使用boto、python和amazons3

如果我使用

[输入列表的key.name(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]

在S3中基本上没有文件夹这样的东西。在内部,所有内容都存储为键,如果键名中有斜杠字符,客户端可能会决定将其显示为文件夹


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

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

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

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

( 查看分隔符标题。)

此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/
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
如果您传入一个前缀为“”、分隔符为“/”的列表,您将得到以下结果:

mybucket/files/
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/
如果您传入一个前缀为“mybucket/files/”和分隔符“/”的列表,您将得到以下结果:

mybucket/files/
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/
如果您传入一个前缀为“mybucket/files/pdf/”和分隔符“/”的列表,您将得到以下结果:

mybucket/files/
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中实现这一点。希望有一种方法可以通过。

boto界面允许您列出bucket的内容并给出条目的前缀。 这样,您就可以拥有普通文件系统中目录的条目:

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

基于sethwm的答案:

要获取顶级目录,请执行以下操作:

list(bucket.list("", "/"))
要获取
文件的子目录

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

依此类推。

正如j1m建议的一种注释方法所指出的,该方法返回一个前缀对象。如果要查找名称/路径,可以使用变量name。例如:

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/
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

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

如果您希望所有文件及其url都位于文件夹中

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
如果您只需要空文件夹

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

然后可以在以后递归读取。

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

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

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

两个返回的对象(前缀或键对象)都具有
.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)

使用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")

我发现使用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 = session.client('s3')
folder_list = list_folders(s3_client, bucket_name)
for folder in folder_list:
    print('Folder found: %s' % folder)
参考文献:


这太好了,文档肯定会引导我朝这个方向前进,但我似乎没有得到钥匙列表。相反,我得到了一个带有键和
boto.s3.prefix.prefix()
对象的列表,我真的不知道如何处理它。有什么想法吗?bucket.list会生成前缀对象列表。
name
属性可能就是您要查找的内容。需要注意的是,要获取目录,
前缀
(第一个参数)应该以分隔符结尾。在第二个示例中,why is
new/abc.pdf
以分隔符“/”列出,前缀为
mybucket/files/pdf/
。我想用分隔符“/”是一个内部对象,不应该被列出@sethwm@Wordzilla,那是个错误。谢谢你抓住它,谢谢。今天的脚本对我很有帮助:)如果你想得到所有的bucket,你可以将上面的内容包装成bucket=conn.get_all_bucket,然后是bucket in bucket:然后继续使用bucket.list。。。。e、 g.>>>bucket=S3Connection()。获取bucket中bucket的所有bucket()>>>:。。。对于bucket.list()中的文件夹:。。。print folder.name列出了该前缀路径中的所有目录和文件。欢迎使用此代码段,并可能提供一些帮助,这将是解决问题的方法和原因。记住,你是在将来回答读者的问题,而不仅仅是现在提问的人!请您的回答添加解释,并说明适用的限制和假设。@TobySpeight,我添加了一些附加信息。谢谢您的评论。我可以通过更改
session.cli来实现这一点