Python Boto3 S3:获取文件而不获取文件夹
使用boto3,如何在不检索文件夹的情况下检索S3存储桶中的所有文件 考虑以下文件结构:Python Boto3 S3:获取文件而不获取文件夹,python,amazon-web-services,amazon-s3,boto3,Python,Amazon Web Services,Amazon S3,Boto3,使用boto3,如何在不检索文件夹的情况下检索S3存储桶中的所有文件 考虑以下文件结构: file_1.txt folder_1/ file_2.txt file_3.txt folder_2/ folder_3/ file_4.txt 在这个例子中,我只对这4个文件感兴趣 编辑: 手动解决方案是: def count_files_in_folder(prefix): total = 0 keys = s3_cli
file_1.txt
folder_1/
file_2.txt
file_3.txt
folder_2/
folder_3/
file_4.txt
在这个例子中,我只对这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/file_2.txt
folder_1/file_3.txt
folder_1/folder_2/folder_3/file_4.txt
S3中没有文件夹。您拥有四个名为:
file_1.txt
folder_1/file_2.txt
folder_1/file_3.txt
folder_1/folder_2/folder_3/file_4.txt
这些是S3中对象的实际名称。如果您希望以以下方式结束:
file_1.txt
file_2.txt
file_3.txt
file_4.txt
所有文件都位于本地文件系统上的同一目录中,您需要操纵对象的名称,以便仅除去文件名。类似这样的方法会奏效:
import os.path
full_name = 'folder_1/folder_2/folder_3/file_4.txt'
file_name = os.path.basename(full_name)
变量
file\u name
将包含'file\u 4.txt'
S3是一个对象存储。它不在目录树下存储文件/对象。
新来者总是混淆他们给出的“文件夹”选项,这实际上是对象的任意前缀
对象前缀
是一种通过预定义的固定文件名(键)前缀结构检索对象的方法,例如
您可以想象使用一个文件系统,它不允许您创建目录,但允许您使用斜杠“/”或反斜杠“\”作为分隔符创建文件名,并且您可以用一个公共前缀表示文件的“级别”
因此,在S3中,您可以使用以下命令来“模拟不是目录的目录”
folder1-folder2-folder3-myobject
folder1/folder2/folder3/myobject
folder1\folder2\folder3\myobject
如您所见,无论您使用何种类型的任意文件夹分隔符(分隔符),对象名都可以存储在S3中
但是,为了帮助用户将大量文件传输到S3,aws cli、S3_transfer api等工具试图简化该步骤,并按照您的输入本地文件夹结构创建对象名
因此,如果您确定所有S3对象都使用/
或\
作为分隔符,则可以使用S3transfer或AWSCcli等工具通过使用密钥名进行简单下载
下面是使用资源迭代器的快速脏代码。使用s3.resource.object.filter将返回迭代器,该迭代器不具有与list\u objects()/list\u objects\u v2()相同的1000个键限制
筛选文件夹的一种方法是,如果确定没有文件以正斜杠结尾,则检查对象的结束字符:
for object_summary in objects.all():
if object_summary.key[-1] == "/":
continue
如其他答案所述,s3实际上没有目录树。但是,通过使用分页器,s3“文件夹”的大小为零,这是一个方便的解决方法。如果bucket中的所有文件的大小都大于0(当然,您需要调整区域),则此代码段将打印出所需的输出: 过滤是使用
注意:当然,这也会排除大小为0的文件,但通常不需要存储空文件。使用
v2
还可以获得文件的大小,因此可以过滤密钥
s3_client
.list_objects_v2(bucket: bucket_name, prefix: prefix)
.select { |e| e[:size] > 0 }
.map { |e| e[:key] }
在S3中实际上有“文件夹”,它们被表示为一个带有附加斜杠的键。文件夹的大小也为零,看起来像AWS S3 web控制台GUI中的文件夹。所以我基本上想知道的是,是否有可能对以斜杠结尾的键进行排序。最好不要手动操作(如果可能的话)不,S3中确实没有文件夹。如果对bucket执行
ListObjects
API请求,您将看到上面列出的四个文件名。S3允许您指定分隔符(“/”,默认情况下),然后它将允许您导航对象,就像有文件夹一样,但S3中没有存储表示文件夹的对象folder1
。没有办法告诉S3服务只返回基本文件名。您必须获得所有对象的列表,然后操纵对象名称以仅提取基本文件名。不,先生,一个列表将返回7个对象@garnaat这是一个很好的答案,但它需要某种重复的文件名处理。如果存在folder1/file.txt
和folder2/file.txt
,当您将两者保存到同一个本地目录时,其中一个将覆盖另一个。我真的很困惑S3中不存在的文件夹,因为(正如我刚才所说)控制台上的一个大按钮创建文件夹,我在调用列表对象时检索文件夹。但你是对的,我在S3文档中多次提到文件夹不存在。那它们怎么会以零尺寸物体的形式存在?!
for object_summary in objects.all():
if object_summary.key[-1] == "/":
continue
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`][]")]
s3_client
.list_objects_v2(bucket: bucket_name, prefix: prefix)
.select { |e| e[:size] > 0 }
.map { |e| e[:key] }