Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/amazon-web-services/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python Boto3 S3:获取文件而不获取文件夹_Python_Amazon Web Services_Amazon S3_Boto3 - Fatal编程技术网

Python 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

使用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_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] }