web-dev-qa-db-ja.com

python botoを使用してAmazon S3のフォルダーのみのリストを取得するにはどうすればよいですか

ボトと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]
28
user1958218

sethwmの答えに基づいて:

トップレベルのディレクトリを取得するには:

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

filesのサブディレクトリを取得するには:

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

等々。

40
j1m

J1mによって提案されたコメントアプローチの1つで指摘したように、プレフィックスオブジェクトを返します。名前/パスの後にいる場合は、変数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
17
Wawrzek

pythonまたはbotoがわからないため、これは不完全な答えになりますが、質問の根底にある概念についてコメントしたいと思います。

他のポスターの1つは正しかったです。S3にはディレクトリという概念はありません。フラットなキー/値のペアのみがあります。多くのアプリケーションは、ディレクトリエントリを示す特定の区切り文字を装います。たとえば、「/」または「\」。一部のアプリは、「ディレクトリ」が空になった場合でもリスト結果に表示できるように、ダミーファイルを配置するだけです。

バケット全体をプルダウンして、ローカルでフィルタリングする必要は必ずしもありません。 S3には、パス区切り文字( "/"、 "\"、 "|"、 "foobar"など)とみなすものを指定する区切りリストの概念があり、S3は、ユーザーに似た仮想結果を返します。欲しいです。

http://docs.aws.Amazon.com/AmazonS3/latest/API/RESTBucketGET.html (区切り記号のヘッダーを見てください。)

このAPIは、1レベルのディレクトリを取得します。あなたの例にあった場合:

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 /」と区切り文字「/」のリストを渡した場合、結果が得られます。

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でこれをどのように行うかはわかりません。うまくいけば、通り抜ける方法があります。

13
sethwm

基本的に、S3にはフォルダーのようなものはありません。内部的にはすべてがキーとして保存され、キー名にスラッシュ文字が含まれている場合、クライアントはそれをフォルダーとして表示することを決定する場合があります。

それを念頭に置いて、最初にすべてのキーを取得してから、正規表現を使用して、スラッシュを含むパスを除外する必要があります。あなたが今持っている解決策はすでに良いスタートです。

8
j0nes

ボト接続に成功したと思います。興味のあるディレクトリが1つしかない場合(例で提供したように)、できることは、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)
_
5
Erica Jh Lee

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
2
bambata

ここでの問題は、他の人から言われているように、フォルダーには必ずしもキーがないため、/文字の文字列を検索し、その中からフォルダーを把握する必要があるということです。フォルダー構造を模した再帰的な辞書を生成する1つの方法を次に示します。

フォルダー内のすべてのファイルとその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

これは後で再帰的に読み取ることができます。

2
Nathan Hazzard

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)

参照:

2