Amazon S3 boto - wie lösche ich einen Ordner?

87

Ich habe in s3 einen Ordner mit dem Namen "test" erstellt und "test_1.jpg", "test_2.jpg" in "test" verschoben.

Wie kann ich mit boto den Ordner "test" löschen?

wade huang
quelle
1
@pyCthon Falsche Technologie. Versuchen Sie es nochmal.
Devinbost

Antworten:

61

In S3 sind keine Ordner vorhanden. Stattdessen bilden die Schlüssel einen flachen Namespace. Ein Schlüssel mit Schrägstrichen im Namen wird jedoch speziell in einigen Programmen angezeigt, einschließlich der AWS-Konsole (siehe zum Beispiel Amazon S3 Boto - Wie erstelle ich einen Ordner? ).

Anstatt "ein Verzeichnis" zu löschen, können (und müssen) Sie Dateien nach Präfix auflisten und löschen. Im Wesentlichen:

for key in bucket.list(prefix='your/directory/'):
    key.delete()

Die anderen Antworten auf dieser Seite bieten jedoch effizientere Ansätze.


Beachten Sie, dass das Präfix nur mit der Dummy-Zeichenfolgensuche durchsucht wird. Wenn das Präfix your/directorywäre, dh ohne den angehängten Schrägstrich, würde das Programm auch gerne löschen your/directory-that-you-wanted-to-remove-is-definitely-not-t‌​his-one.

Weitere Informationen finden Sie unter S3-Botolistenschlüssel. Manchmal wird der Verzeichnisschlüssel zurückgegeben.

Antti Haapala
quelle
1
Wie lösche ich das Verzeichnis? Wird dieses Verzeichnis automatisch gelöscht, wenn alle Dateien in diesem Verzeichnis gelöscht werden?
Wade Huang
Vielen Dank .. Ich habe es beendet ~
Wade Huang
@wadehuang - Können Sie Ihren Code zum Löschen von Ordnern freigeben?
Letsc
So löschen Sie Dateien in einem Ordner von s3, die in Python 2 Tage alt sind. Habe dies in meinem s3 - Bucket / 1 / Backups / (10 Dateien) muss alle Dateien entfernen, die zwei Tage alt sind
艾瑪艾瑪 艾瑪
189

Hier ist die Version 2018 (fast 2019):

s3 = boto3.resource('s3')
bucket = s3.Bucket('mybucket')
bucket.objects.filter(Prefix="myprefix/").delete()
Raz
quelle
22
Dies ist bei weitem die beste Antwort.
user554481
1
Jemand könnte es nützlich finden zu wissen, dass Bucket.objects.all (). delete () den gesamten Bucket leert, ohne ihn zu löschen, unabhängig davon, wie viele Objekte es gibt (dh es ist nicht betroffen, aber das Limit von 1000 Elementen). Siehe: boto3.amazonaws.com/v1/documentation/api/latest/reference/…
fabiog
1
Hallo Raz, das funktioniert bei mir nicht, ich bekomme einfach leere eckige Klammern, dh []
Soyf
Leider unterstützt dies kein Suffix :(
Anum Sheraz
Das Tolle ist, dass diese Lösung auch mit mehr als 1000 Objekten
funktioniert
45

Ich habe das Gefühl, dass es eine Weile her ist und boto3 verschiedene Möglichkeiten hat, dieses Ziel zu erreichen. Dies setzt voraus , Sie löschen möchten Test „Ordner“ und alle seine Objekte Hier ist eine Möglichkeit:

s3 = boto3.resource('s3')
objects_to_delete = s3.meta.client.list_objects(Bucket="MyBucket", Prefix="myfolder/test/")

delete_keys = {'Objects' : []}
delete_keys['Objects'] = [{'Key' : k} for k in [obj['Key'] for obj in objects_to_delete.get('Contents', [])]]

s3.meta.client.delete_objects(Bucket="MyBucket", Delete=delete_keys)

Dies sollte zwei Anforderungen stellen, eine zum Abrufen der Objekte im Ordner und die zweite zum Löschen aller Objekte in diesem Ordner.

https://boto3.readthedocs.org/en/latest/reference/services/s3.html#S3.Client.delete_objects

Patrick
quelle
Dies ist bei weitem die schnellste Lösung.
deepelement
2
Dies ist die schnellste Lösung list_objects. Beachten Sie jedoch, dass nicht mehr als 1000 Schlüssel zurückgegeben werden können, sodass Sie diesen Code mehrmals ausführen müssen.
Lampensklave
4
Sie können Paginator verwenden, wenn Sie mehr als 1k Objekte haben - siehe meine Antwort unten.
Dmitrybelyakov
@deepelement, und es funktioniert nur in boto3, nicht boto
avocado
1
Dies funktioniert hervorragend und Sie können es von einem Python-Lambda aus ausführen, indem Sie den obigen Code in eine lambda_handler-Funktion einfügen : import boto3; def lambda_handler(event, context): '''Code from above'''. Stellen Sie sicher, dass Sie Ihrem Lambda die Berechtigung zum Löschen aus S3 erteilen und das Zeitlimit verlängern.
Nadir Sidi
21

Sie können Bucket.delete_keys () mit einer Liste von Schlüsseln verwenden (bei einer großen Anzahl von Schlüsseln war dies eine Größenordnung schneller als bei Verwendung von key.delete).

Etwas wie das:

delete_key_list = []
for key in bucket.list(prefix='/your/directory/'):
    delete_key_list.append(key)
    if len(delete_key_list) > 100:
        bucket.delete_keys(delete_key_list)
        delete_key_list = []

if len(delete_key_list) > 0:
    bucket.delete_keys(delete_key_list)
David Fooks
quelle
20

Eine leichte Verbesserung von Patricks Lösung. Wie Sie vielleicht wissen, haben beide list_objects()und delete_objects()ein Objektlimit von 1000. Aus diesem Grund müssen Sie die Auflistung paginieren und in Blöcken löschen. Das ist ziemlich universell und Sie können geben Prefixzu paginator.paginate()zu löschen Unterverzeichnisse / Pfade

client = boto3.client('s3', **credentials)
paginator = client.get_paginator('list_objects_v2')
pages = paginator.paginate(Bucket=self.bucket_name)

delete_us = dict(Objects=[])
for item in pages.search('Contents'):
    delete_us['Objects'].append(dict(Key=item['Key']))

    # flush once aws limit reached
    if len(delete_us['Objects']) >= 1000:
        client.delete_objects(Bucket=bucket, Delete=delete_us)
        delete_us = dict(Objects=[])

# flush rest
if len(delete_us['Objects']):
    client.delete_objects(Bucket=bucket, Delete=delete_us)
dmitrybelyakov
quelle
2
Und wenn Sie sich auf ein "Verzeichnis" beschränken möchten, verwenden Sie das PrefixSchlüsselwort in paginator.paginate()Alle Optionen anzeigen
Chad
1
Mit dem Prefixvon @Chad vorgeschlagenen Filter musste ich if item is not Nonevor dem Löschen eine Prüfung hinzufügen (da einige meiner S3-Präfixe nicht existierten / keine Objekte hatten)
y2k-shubham
1

Wenn die Versionierung im S3-Bucket aktiviert ist:

s3 = boto3.resource('s3')
bucket = s3.Bucket('mybucket')
bucket.object_versions.filter(Prefix="myprefix/").delete()
Dan-Dev
quelle