Python Boto3 S3:仅列出当前目录文件,忽略子目录文件

4

我想从前缀文件夹下载文件,而不是前缀文件夹内的子目录。我运行下面的代码,但它列出了包括子目录在内的前缀文件夹内的所有文件。有没有办法只列出前缀文件夹中的文件?

bucket = aws_resource_session.Bucket(bucket_name)
for obj in bucket.objects.filter(Prefix=s3_end_point_properties["prefix"]):
    print(obj.key)

谢谢,Imran Khan


如果 obj.get()['ContentType'] == 'application/x-directory': - Ευάγγελος Γρηγορόπουλος
2个回答

7
使用低级别的客户端界面Client,而不是使用较高级别的资源接口Bucket,后者仅会给出存储桶内所有对象的列表。具体来说,在调用list_objects_v2时,如果包括“Delimiter”参数,则结果将返回给定前缀中“Contents”的对象和“子文件夹”在“CommonPrefixes”中。

示例:

import boto3
s3 = boto3.client("s3")

rsp = s3.list_objects_v2(Bucket="mybucket", Prefix="myprefix/", Delimiter="/")

print("Objects:", list(obj["Key"] for obj in rsp["Contents"]))
print("Sub-folders:", list(obj["Prefix"] for obj in rsp["CommonPrefixes"]))

使用 Prefix="csv/" 的示例输出:

Objects: ['csv/a.csv', 'csv/b.csv', 'csv/c.csv']
Sub-folders: ['csv/corrupt/', 'csv/complete/']

如果您不包括Delimiter参数,则该前缀及以下的所有对象都将在"Contents"中出现,例如:
Objects: ['csv/a.csv', 'csv/b.csv', 'csv/c.csv', 'csv/corrupt/d.csv', 'csv/complete/e.csv']

在我的实验中,第一个示例代码的输出为:“Objects: ['csv /','csv / a.csv','csv / b.csv','csv / c.csv']”。我想知道如何摆脱目录名称,因为我只想列出目录中的文件,而不是目录本身。 - Zhiwei
1
@Zhiwei 如果“csv /”出现在内容中,则是因为某个人或某个进程明确创建了名为“csv /”的对象。通常,当有人使用AWS S3控制台并创建名为“csv”的文件夹时,就会发生这种情况。您将不得不自己过滤结果,这应该很容易做到(只需过滤掉以“/”结尾的字符串)。例如:[f for f in objects if not f.endswith('/')] - jarmod

2
在s3中没有“文件夹”这个概念。可以将所有对象想象成在根目录下的单个“文件夹”中。文件名很长,其中包含“/”,这就是所有对象存储的方式。AWS只是为了方便人们使用熟悉的文件夹结构。
当您指定前缀时,将获取以该前缀开头的每个对象。您可以使用Python的标准字符串操作库来提取下载之前不需要的内容。
您知道每个对象都有您的前缀,因此可以设计一种方法先从每个键中删除前缀,然后检查文件名(即s3键)中是否仍然有“/”。如果有,“/”则表示它位于文件夹或子文件夹中(我使用您使用的术语使其更清晰),这是您不想要的。
例如:
objects = bucket.objects.filter(Prefix=prefix)
[obj for obj in objects if '/' not in obj.key.replace(prefix,'')]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接