ボトと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]
sethwmの答えに基づいて:
トップレベルのディレクトリを取得するには:
list(bucket.list("", "/"))
files
のサブディレクトリを取得するには:
list(bucket.list("files/", "/")
等々。
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
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でこれをどのように行うかはわかりません。うまくいけば、通り抜ける方法があります。
基本的に、S3にはフォルダーのようなものはありません。内部的にはすべてがキーとして保存され、キー名にスラッシュ文字が含まれている場合、クライアントはそれをフォルダーとして表示することを決定する場合があります。
それを念頭に置いて、最初にすべてのキーを取得してから、正規表現を使用して、スラッシュを含むパスを除外する必要があります。あなたが今持っている解決策はすでに良いスタートです。
ボト接続に成功したと思います。興味のあるディレクトリが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)
_
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
ここでの問題は、他の人から言われているように、フォルダーには必ずしもキーがないため、/文字の文字列を検索し、その中からフォルダーを把握する必要があるということです。フォルダー構造を模した再帰的な辞書を生成する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
これは後で再帰的に読み取ることができます。
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)
参照: