Amazon S3 boto - Comment supprimer un dossier?

87

J'ai créé un dossier en s3 nommé "test" et j'ai poussé "test_1.jpg", "test_2.jpg" dans "test".

Comment puis-je utiliser boto pour supprimer le dossier "test"?

wade huang
la source
1
@pyCthon Mauvaise technologie. Réessayer.
devinbost

Réponses:

61

Il n'y a pas de dossiers dans S3. Au lieu de cela, les clés forment un espace de noms plat. Cependant, une clé avec des barres obliques dans son nom apparaît spécialement dans certains programmes, y compris la console AWS (voir par exemple Amazon S3 boto - comment créer un dossier? ).

Au lieu de supprimer "un répertoire", vous pouvez (et devez) lister les fichiers par préfixe et supprimer. En substance:

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

Cependant, les autres réponses accomplies sur cette page présentent des approches plus efficaces.


Notez que le préfixe est simplement recherché en utilisant la recherche de chaîne factice. Si le préfixe était your/directory, c'est-à-dire sans la barre oblique de fin ajoutée, le programme supprimerait également avec plaisir your/directory-that-you-wanted-to-remove-is-definitely-not-t‌​his-one.

Pour plus d'informations, voir S3 boto list keys renvoie parfois une clé de répertoire.

Antti Haapala
la source
1
Comment supprimer le répertoire? Si ce répertoire sera supprimé automatiquement lorsque tous les fichiers de ce répertoire seront supprimés?
wade huang
Merci .. Je l'ai fini ~
wade huang
@wadehuang - pourriez-vous partager votre code sur la suppression de dossiers?
letc
Comment supprimer des fichiers dans le dossier de s3 qui ont 2 jours en python. avoir ceci dans mon s3 - bucket / 1 / backups / (10 fichiers) besoin de supprimer tous les fichiers qui ont deux jours
艾瑪艾瑪 艾瑪
187

Voici la version 2018 (presque 2019):

s3 = boto3.resource('s3')
bucket = s3.Bucket('mybucket')
bucket.objects.filter(Prefix="myprefix/").delete()
Raz
la source
22
C'est de loin la meilleure réponse.
user554481
1
quelqu'un pourrait trouver utile de savoir que bucket.objects.all (). delete () vide le bucket entier sans le supprimer, quel que soit le nombre d'objets (c'est-à-dire qu'il n'est pas affecté mais la limite de 1000 éléments). Voir: boto3.amazonaws.com/v1/documentation/api/latest/reference/…
fabiog
1
Salut Raz, cela ne fonctionne pas pour moi, je reçois simplement des crochets vides, c'est-à-dire []
Soyf
Malheureusement, cela ne prend pas en charge le suffixe :(
Anum Sheraz
La grande chose est que cette solution fonctionne même avec plus de 1000 objets
Mabyn
45

Je sens que cela fait un moment et que boto3 a plusieurs façons d'atteindre cet objectif. Cela suppose que vous souhaitiez supprimer le "dossier" de test et tous ses objets. Voici une solution:

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)

Cela devrait faire deux requêtes, une pour récupérer les objets dans le dossier, la seconde pour supprimer tous les objets dans ledit dossier.

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

Patrick
la source
C'est de loin la solution la plus rapide.
deepelement
2
C'est la solution la plus rapide, mais gardez à l'esprit que list_objectsvous ne pouvez pas renvoyer plus de 1000 clés, vous devez donc exécuter ce code plusieurs fois.
Lampeslave
4
Vous pouvez utiliser paginator si vous avez plus de 1k objets - voir ma réponse ci-dessous.
dmitrybelyakov
@deepelement, et cela ne fonctionne que dans boto3, pas de boto
avocat
1
Cela fonctionne très bien, et vous pouvez l' exécuter à partir d' un lambda Python en mettant le code ci - dessus dans une fonction lambda_handler: import boto3; def lambda_handler(event, context): '''Code from above'''. Assurez-vous de donner à votre Lambda l'autorisation de supprimer de S3 et de prolonger le délai.
Nadir Sidi
21

Vous pouvez utiliser bucket.delete_keys () avec une liste de clés (avec un grand nombre de clés, j'ai trouvé que c'était un ordre de grandeur plus rapide que d'utiliser key.delete).

Quelque chose comme ça:

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
la source
20

Une légère amélioration par rapport à la solution de Patrick. Comme vous le savez peut-être, les deux list_objects()et delete_objects()ont une limite d'objet de 1000. C'est pourquoi vous devez paginer la liste et la supprimer en morceaux. C'est assez universel et vous pouvez donner Prefixà paginator.paginate()sous - répertoires / chemins de suppression

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
la source
2
Et si vous voulez vous limiter à un "répertoire" utilisez le Prefixmot - clé dans paginator.paginate()Voir toutes les options: boto3.readthedocs.io/en/latest/reference/services
Tchad
1
avec le Prefixfiltre suggéré par @Chad , j'ai dû ajouter une if item is not Nonevérification avant la suppression (car certains de mes préfixes S3 n'existaient pas / n'avaient pas d'objets)
y2k-shubham
1

Si le contrôle de version est activé sur le compartiment S3:

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