web-dev-qa-db-ja.com

Boto3 S3:フォルダーを取得せずにファイルを取得する

Boto3を使用して、フォルダーを取得せずにS3バケット内のすべてのファイルを取得するにはどうすればよいですか?

次のファイル構造を検討してください。

file_1.txt
folder_1/
    file_2.txt
    file_3.txt
    folder_2/
        folder_3/
            file_4.txt

この例では、Imは4つのファイルにのみ関心があります。

編集:

手動による解決策は次のとおりです。

def count_files_in_folder(prefix):
    total = 0
    keys = s3_client.list_objects(Bucket=bucket_name, Prefix=prefix)
    for key in keys['Contents']:
        if key['Key'][-1:] != '/':
            total += 1
    return total

この場合、合計は4になります。

私がやったら

count = len(s3_client.list_objects(Bucket=bucket_name, Prefix=prefix))

結果は7つのオブジェクト(4つのファイルと3つのフォルダー)になります。

file.txt
folder_1/
folder_1/file_2.txt
folder_1/file_3.txt
folder_1/folder_2/
folder_1/folder_2/folder_3/
folder_1/folder_2/folder_3/file_4.txt

ただ欲しい:

file.txt
folder_1/file_2.txt
folder_1/file_3.txt  
folder_1/folder_2/folder_3/file_4.txt
3
Vingtoft

他の回答で述べられているように、s3には実際にはディレクトリツリーがありません。ただし、s3「フォルダー」のサイズがゼロであるという事実を利用して、ページネーターを使用することで便利な回避策があります。このコードスニペットは、バケット内のすべてのファイルのサイズが0より大きい場合に目的の出力を出力します(もちろん、リージョンを調整する必要があります)。

bucket_name = "bucketname"
s3 = boto3.client('s3', region_name='eu-central-1')
paginator = s3.get_paginator('list_objects')
[print(page['Key']) for page in paginator.paginate(Bucket=bucket_name).search("Contents[?Size > `0`][]")]

フィルタリングは JMESPath を使用して行われます。

注:もちろん、これはサイズ0のファイルも除外しますが、通常は空のファイル用のストレージは必要ありません。

0
airborne