Подтвердить что ты не робот

Как я могу получить список только папок в amazon S3, используя python boto

Я использую 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]
4b9b3361

Ответ 1

построение на sethwm ответе:

Чтобы получить каталоги верхнего уровня:

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

Чтобы получить подкаталоги files:

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

и т.д.

Ответ 2

Как указано в одном из комментариев, предложенном 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

Ответ 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/

И вы передали в СПИСОК с префиксом "" и разделителем "/", вы получили бы результаты:

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, я понятия не имею. Надеюсь, есть способ пройти.

Ответ 4

В принципе нет такой вещи, как папка в S3. Внутренне все хранится как ключ, и если имя ключа имеет в нем символ косой черты, клиенты могут решить показать его как папку.

С учетом этого вы должны сначала получить все ключи, а затем использовать регулярное выражение, чтобы отфильтровать пути, которые включают в себя косую черту. Решение, которое у вас есть прямо сейчас, является хорошим началом.

Ответ 5

Я вижу, что вы успешно сделали соединение 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)

Ответ 6

Интерфейс 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

Ответ 7

Проблема здесь, как было сказано другими, заключается в том, что папка не обязательно содержит ключ, поэтому вам придется искать строки для символа/и определять их папки через это. Здесь один из способов генерации рекурсивного словаря, имитирующего структуру папок.

Если вы хотите, чтобы все файлы и их 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

Затем это может быть рекурсивно прочитано позже.

Ответ 8

Я нашел следующее, чтобы работать с 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)

Refs.:

Ответ 9

Полный пример с boto3 с использованием клиента S3

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