【问题标题】:How can I get the list of only folders in amazon S3 using python boto?如何使用 python boto 获取亚马逊 S3 中唯一文件夹的列表?
【发布时间】:2013-06-26 20:12:36
【问题描述】:

我正在使用 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]

【问题讨论】:

  • 我认为你的解决方案是最好的,我可以直接得到文件路径。

标签: python amazon-s3 boto


【解决方案1】:

以sethwm 的回答为基础:

获取顶级目录:

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

获取files的子目录:

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

等等。

【讨论】:

  • 太好了,文档当然引导我朝这个方向发展,但我似乎没有得到密钥列表。相反,我得到一个带有键和 boto.s3.prefix.Prefix() 对象的列表,我真的不知道该怎么做。有什么想法吗?
  • bucket.list 确实会产生一个前缀对象列表。 name 属性可能是您正在寻找的。​​span>
  • 重要的是要注意,要获取目录,prefix(第一个参数)应该以分隔符结尾
【解决方案2】:

正如 j1m 建议的一种 cmets 方法所指出的,它返回一个前缀对象。如果你在一个名字/路径之后,你可以使用变量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

【讨论】:

  • 如果您想获取所有存储桶,您可以将上述内容包装在 buckets = conn.get_all_buckets 中,然后 for buckets in buckets: 然后继续使用 bucket.list....例如>>> buckets = S3Connection().get_all_buckets() >>> 对于 buckets 中的 bucket:... 对于 bucket.list() 中的文件夹: ... print folder.name
【解决方案3】:

这将是一个不完整的答案,因为我不知道 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/

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

mybucket/files/

如果您传入带有前缀“mybucket/files/”和分隔符“/”的 LIST,您会得到结果:

mybucket/files/pdf/

如果你传入一个带有前缀“mybucket/files/pdf/”和分隔符“/”的 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/2011/

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

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

【讨论】:

  • 为什么new/abc.pdf 在第二个示例中以分隔符“/”列出,前缀为mybucket/files/pdf/。我想用分隔符 '/' 它是一个内部对象,不应该被列出。 @sethwm
  • @Wordzilla,这是一个错误。感谢收看。
  • 谢谢。今天的脚本对我很有帮助:)
【解决方案4】:

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

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

【讨论】:

    【解决方案5】:

    我发现以下内容可以使用 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)
    

    参考:

    【讨论】:

    • 我可以通过将 session.client() 更改为 boto3.client() 来完成这项工作
    • 分隔符选项帮助我仅在根目录中获取对象并跳过创建的文件夹。
    • 这真的回答了这个问题吗?它不会打印出存储桶中的所有文件夹,而只会打印出前缀的第一个根级别。
    • 只需将Prefix='' 更改为您关心的任何前缀,它就会打印该级别的文件夹
    【解决方案6】:

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

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

    我尝试了几种方法,如果您确实选择在bucket.list() 中使用delimiter= 参数,则返回的对象是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)
    

    【讨论】:

    • 虽然欢迎使用此代码 sn-p,并且可能会提供一些帮助,但它会是 greatly improved if it included an explanation of how 和 why 这解决了问题。请记住,您正在为将来的读者回答问题,而不仅仅是现在提问的人!请edit您的答案添加解释,并说明适用的限制和假设。
    • @TobySpeight ,我添加了一些附加信息。感谢您的评论。
    【解决方案7】:

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

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

    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
    

    这可以在以后递归读出。

    【讨论】:

      【解决方案8】:

      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
      

      【讨论】:

      • 这会列出该前缀路径中的所有目录和文件
      【解决方案9】:

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

      【讨论】:

        猜你喜欢
        • 2010-12-19
        • 2015-10-05
        • 1970-01-01
        • 2022-07-02
        • 2013-08-06
        • 1970-01-01
        • 1970-01-01
        • 2013-09-24
        • 2018-01-22
        相关资源
        最近更新 更多