Ho creato una cartella in s3 denominata "test" e ho inserito "test_1.jpg", "test_2.jpg" in "test".
Come posso utilizzare boto per eliminare la cartella "test"?
Ho creato una cartella in s3 denominata "test" e ho inserito "test_1.jpg", "test_2.jpg" in "test".
Come posso utilizzare boto per eliminare la cartella "test"?
Risposte:
Non ci sono non le cartelle in S3. Invece, le chiavi formano uno spazio dei nomi piatto. Tuttavia, una chiave con barre nel nome viene visualizzata specialmente in alcuni programmi, inclusa la console AWS (vedi ad esempio Amazon S3 boto - come creare una cartella? ).
Invece di eliminare "una directory", puoi (e devi) elencare i file per prefisso ed eliminare. In sostanza:
for key in bucket.list(prefix='your/directory/'):
key.delete()
Tuttavia, le altre risposte complete in questa pagina presentano approcci più efficienti.
Si noti che la ricerca del prefisso viene eseguita utilizzando la ricerca di stringhe fittizie. Se il prefisso fosse , cioè, senza la barra finale aggiunta, anche il programma eliminerebbe felicemente your/directory
your/directory-that-you-wanted-to-remove-is-definitely-not-this-one
.
Per ulteriori informazioni, vedere Le chiavi dell'elenco boto S3 a volte restituiscono la chiave della directory.
Ecco la versione 2018 (quasi 2019):
s3 = boto3.resource('s3')
bucket = s3.Bucket('mybucket')
bucket.objects.filter(Prefix="myprefix/").delete()
Sento che è passato un po 'di tempo e boto3 ha diversi modi per raggiungere questo obiettivo. Questo presuppone che tu voglia eliminare la "cartella" di prova e tutti i suoi oggetti. Ecco un modo:
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)
Questo dovrebbe fare due richieste, una per recuperare gli oggetti nella cartella, la seconda per eliminare tutti gli oggetti in detta cartella.
https://boto3.readthedocs.org/en/latest/reference/services/s3.html#S3.Client.delete_objects
list_objects
non può restituire più di 1000 chiavi, quindi devi eseguire questo codice più volte.
boto3
, non boto
import boto3; def lambda_handler(event, context): '''Code from above'''
. Assicurati di concedere al tuo Lambda l'autorizzazione per eliminare da S3 ed estendere il timeout.
Puoi usare bucket.delete_keys () con un elenco di chiavi (con un numero elevato di chiavi ho riscontrato che questo è un ordine di grandezza più veloce rispetto all'utilizzo di key.delete).
Qualcosa come questo:
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)
Un leggero miglioramento rispetto alla soluzione di Patrick. Come forse saprai, entrambi list_objects()
e delete_objects()
hanno un limite di 1000 oggetti. Questo è il motivo per cui devi impaginare l'elenco ed eliminare in blocchi. Questo è abbastanza universale e si può dare Prefix
a paginator.paginate()
sottodirectory cancellare / percorsi
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)
Prefix
parola chiave in paginator.paginate()
Vedi tutte le opzioni: boto3.readthedocs.io/en/latest/reference/services/…
Prefix
filtro suggerito da @Chad , ho dovuto aggiungere un if item is not None
controllo prima della cancellazione (poiché alcuni dei miei prefissi S3 non esistevano / non avevano oggetti)
Se il controllo delle versioni è abilitato nel bucket S3:
s3 = boto3.resource('s3')
bucket = s3.Bucket('mybucket')
bucket.object_versions.filter(Prefix="myprefix/").delete()
files_to_delete = bucket.object_versions.filter(Prefix="myprefix/")
poi iterare files_to_delete
e chiamare print () quindi delete () su di loro.
Se è necessario filtrare per contenuto oggetto come ho fatto io, il seguente è un modello per la tua logica:
def get_s3_objects_batches(s3: S3Client, **base_kwargs):
kwargs = dict(MaxKeys=1000, **base_kwargs)
while True:
response = s3.list_objects_v2(**kwargs)
# to yield each and every file: yield from response.get('Contents', [])
yield response.get('Contents', [])
if not response.get('IsTruncated'): # At the end of the list?
break
continuation_token = response.get('NextContinuationToken')
kwargs['ContinuationToken'] = continuation_token
def your_filter(b):
raise NotImplementedError()
session = boto3.session.Session(profile_name=profile_name)
s3client = session.client('s3')
for batch in get_s3_objects_batches(s3client, Bucket=bucket_name, Prefix=prefix):
to_delete = [{'Key': obj['Key']} for obj in batch if your_filter(obj)]
if to_delete:
s3client.delete_objects(Bucket=bucket_name, Delete={'Objects': to_delete})