Saya membuat folder di s3 bernama "test" dan saya mendorong "test_1.jpg", "test_2.jpg" ke dalam "test".
Bagaimana cara menggunakan boto untuk menghapus folder "test"?
Saya membuat folder di s3 bernama "test" dan saya mendorong "test_1.jpg", "test_2.jpg" ke dalam "test".
Bagaimana cara menggunakan boto untuk menghapus folder "test"?
Jawaban:
Tidak ada folder di S3. Sebaliknya, kunci membentuk namespace datar. Namun kunci dengan garis miring pada namanya ditampilkan secara khusus di beberapa program, termasuk konsol AWS (lihat misalnya Amazon S3 boto - bagaimana cara membuat folder? ).
Alih-alih menghapus "direktori", Anda dapat (dan harus) membuat daftar file dengan awalan dan menghapus. Intinya:
for key in bucket.list(prefix='your/directory/'):
key.delete()
Namun jawaban lain yang berhasil di halaman ini menampilkan pendekatan yang lebih efisien.
Perhatikan bahwa awalan hanya dicari menggunakan pencarian string dummy. Jika awalannya , yaitu, tanpa menambahkan garis miring, program juga akan dengan senang hati menghapusnya your/directory
your/directory-that-you-wanted-to-remove-is-definitely-not-this-one
.
Untuk informasi selengkapnya, lihat kunci daftar boto S3 terkadang mengembalikan kunci direktori.
Ini adalah versi 2018 (hampir 2019):
s3 = boto3.resource('s3')
bucket = s3.Bucket('mybucket')
bucket.objects.filter(Prefix="myprefix/").delete()
Saya merasa sudah lama dan boto3 memiliki beberapa cara berbeda untuk mencapai tujuan ini. Ini mengasumsikan Anda ingin menghapus tes "folder" dan semua objeknya Berikut adalah salah satu caranya:
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)
Ini harus membuat dua permintaan, satu untuk mengambil objek di folder, yang kedua untuk menghapus semua objek di folder tersebut.
https://boto3.readthedocs.org/en/latest/reference/services/s3.html#S3.Client.delete_objects
list_objects
tidak dapat mengembalikan lebih dari 1000 kunci sehingga Anda perlu menjalankan kode ini beberapa kali.
boto3
, bukan boto
import boto3; def lambda_handler(event, context): '''Code from above'''
. Pastikan Anda memberikan izin Lambda Anda untuk menghapus dari S3 dan memperpanjang batas waktu.
Anda dapat menggunakan bucket.delete_keys () dengan daftar kunci (dengan sejumlah besar kunci, saya menemukan bahwa urutan besarnya lebih cepat daripada menggunakan key.delete).
Sesuatu seperti ini:
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)
Sedikit perbaikan pada solusi Patrick. Seperti yang Anda ketahui, keduanya list_objects()
dan delete_objects()
memiliki batas objek 1000. Inilah sebabnya mengapa Anda harus membuat daftar halaman dan menghapus dalam potongan. Ini sangat universal dan Anda dapat memberikan Prefix
untuk paginator.paginate()
untuk menghapus subdirektori / jalur
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
kata kunci di paginator.paginate()
Lihat semua opsi: boto3.readthedocs.io/en/latest/reference/services/…
Prefix
filter yang disarankan oleh @Chad , saya harus menambahkan tanda if item is not None
centang sebelum menghapus (karena beberapa prefiks S3 saya tidak ada / tidak memiliki objek)
Jika pembuatan versi diaktifkan pada 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/")
iterasi files_to_delete
dan memanggil print () lalu delete () pada mereka.
Jika seseorang perlu memfilter berdasarkan konten objek seperti yang saya lakukan, berikut ini adalah cetak biru untuk logika Anda:
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})