Amazon S3 boto - จะลบโฟลเดอร์ได้อย่างไร


87

ฉันสร้างโฟลเดอร์ใน s3 ชื่อ "test" แล้วดัน "test_1.jpg", "test_2.jpg" เป็น "test"

ฉันจะใช้ boto เพื่อลบโฟลเดอร์ "test" ได้อย่างไร?


1
@pyCthon ผิดเทคโนโลยี ลองอีกครั้ง.
devinbost

คำตอบ:


61

ขณะนี้ไม่มีโฟลเดอร์ใน S3 แต่คีย์จะสร้างเนมสเปซแบบแบน อย่างไรก็ตามคีย์ที่มีเครื่องหมายทับในชื่อจะแสดงเป็นพิเศษในบางโปรแกรมรวมถึงคอนโซล AWS (ดูตัวอย่างเช่นAmazon S3 boto - จะสร้างโฟลเดอร์ได้อย่างไร )

แทนที่จะลบ "ไดเรกทอรี" คุณสามารถ (และต้อง) แสดงรายการไฟล์ตามคำนำหน้าและลบ ในสาระสำคัญ:

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

อย่างไรก็ตามคำตอบอื่น ๆ ที่ประสบความสำเร็จในหน้านี้มีแนวทางที่มีประสิทธิภาพมากกว่า


สังเกตว่าคำนำหน้าถูกค้นหาโดยใช้การค้นหาสตริงจำลอง ถ้าคำนำหน้าเป็นyour/directory, ที่อยู่, your/directory-that-you-wanted-to-remove-is-definitely-not-t‌​his-oneโดยไม่ต้องเฉือนท้ายท้ายโปรแกรมจะยังมีความสุขลบ

สำหรับข้อมูลเพิ่มเติมโปรดดูที่ปุ่มรายการ S3 boto บางครั้งส่งคืนคีย์ไดเรกทอรี


1
จะลบไดเร็กทอรีได้อย่างไร? ถ้าไดเรกทอรีนี้จะถูกลบโดยอัตโนมัติเมื่อไฟล์ทั้งหมดในไดเร็กทอรีนี้ถูกลบ?
ลุย huang

ขอบคุณครับ.. จบแล้วครับ ~
ลุยฮวง

@wadehuang - ช่วยแชร์รหัสเกี่ยวกับการลบโฟลเดอร์ได้ไหม
letsc

วิธีลบไฟล์ในโฟลเดอร์ s3 ที่มีอายุ 2 วันใน python มีสิ่งนี้ใน s3 ของฉัน - ที่เก็บข้อมูล / 1 / การสำรองข้อมูล / (10 ไฟล์) จำเป็นต้องลบไฟล์ทั้งหมดที่มีอายุสองวัน
艾瑪艾瑪艾瑪

202

นี่คือเวอร์ชัน 2018 (เกือบ 2019):

s3 = boto3.resource('s3')
bucket = s3.Bucket('mybucket')
bucket.objects.filter(Prefix="myprefix/").delete()

27
นี่เป็นคำตอบที่ดีที่สุด
user554481

2
บางคนอาจพบว่ามีประโยชน์เมื่อทราบว่า bucket.objects.all (). delete () ล้างที่เก็บข้อมูลทั้งหมดโดยไม่ต้องลบออกไม่ว่าจะมีออบเจ็กต์จำนวนเท่าใดก็ตาม (กล่าวคือไม่ได้รับผลกระทบ แต่ จำกัด 1,000 รายการ) ดู: boto3.amazonaws.com/v1/documentation/api/latest/reference/…
fabiog

1
สวัสดี Raz สิ่งนี้ไม่ได้ผลสำหรับฉันฉันเพิ่งได้รับวงเล็บเหลี่ยมว่างเปล่าเช่น []
Soyf

น่าเศร้าที่สิ่งนี้ไม่รองรับคำต่อท้าย :(
Anum Sheraz

สิ่งที่ยอดเยี่ยมคือโซลูชันนี้ใช้งานได้กับวัตถุมากกว่า 1,000 ชิ้น
Mabyn

46

ฉันรู้สึกว่ามันเป็นเวลานานแล้วและ boto3 ก็มีวิธีต่างๆในการบรรลุเป้าหมายนี้ การดำเนินการนี้จะถือว่าคุณต้องการลบ"โฟลเดอร์" ทดสอบและวัตถุทั้งหมดนี่เป็นวิธีหนึ่ง:

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)

สิ่งนี้ควรส่งคำขอสองครั้งรายการหนึ่งเรียกวัตถุในโฟลเดอร์รายการที่สองเพื่อลบวัตถุทั้งหมดในโฟลเดอร์ดังกล่าว

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


นี่เป็นวิธีแก้ปัญหาที่เร็วที่สุด
deepelement

2
นี่เป็นวิธีแก้ปัญหาที่เร็วที่สุด แต่โปรดทราบว่าlist_objectsไม่สามารถส่งคืนมากกว่า 1,000 คีย์ได้ดังนั้นคุณต้องเรียกใช้รหัสนี้หลายครั้ง
lamplave

4
คุณสามารถใช้ paginator ได้หากคุณมีวัตถุมากกว่า 1k - ดูคำตอบของฉันด้านล่าง
dmitrybelyakov

@deepelement และใช้ได้เฉพาะในboto3boto
avocado

1
นี้ทำงานได้ดีและคุณสามารถเรียกใช้จากแลมบ์ดาหลามโดยการใส่รหัสข้างต้นในการทำงาน lambda_handler import boto3; def lambda_handler(event, context): '''Code from above'''นี้: ตรวจสอบให้แน่ใจว่าคุณได้ให้สิทธิ์ Lambda ของคุณในการลบออกจาก S3 และขยายระยะหมดเวลา
Nadir Sidi

21

คุณสามารถใช้bucket.delete_keys ()กับรายการคีย์ (ด้วยคีย์จำนวนมากฉันพบว่านี่เป็นลำดับขนาดที่เร็วกว่าการใช้ key.delete)

สิ่งนี้:

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)

20

การปรับปรุงโซลูชันของ Patrick เล็กน้อย ดังที่คุณอาจทราบแล้วทั้งสองอย่างlist_objects()และdelete_objects()มีขีด จำกัด ของวัตถุที่ 1,000 นี่คือเหตุผลที่คุณต้องแบ่งหน้ารายการและลบเป็นชิ้น ๆ นี้เป็นสากลสวยและคุณสามารถให้Prefixการpaginator.paginate()ไดเรกทอรีย่อยลบ / เส้นทาง

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)

2
และถ้าคุณต้องการ จำกัด เฉพาะ "ไดเรกทอรี" ให้ใช้Prefixคีย์เวิร์ดในpaginator.paginate()See all options: boto3.readthedocs.io/en/latest/reference/services/…
ชาด

1
ด้วยPrefixตัวกรองที่แนะนำโดย@Chadฉันต้องเพิ่มการif item is not Noneตรวจสอบก่อนที่จะลบ (เนื่องจากไม่มีคำนำหน้า S3 บางตัว / ไม่มีวัตถุ)
y2k-shubham

3

หากเปิดใช้งานการกำหนดเวอร์ชันบนที่เก็บ S3:

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

มีวิธีพิมพ์บางส่วนของสิ่งที่กำลังลบอยู่หรือไม่? ฉันต้องการลบเวอร์ชันก่อนแล้วจึงเป็นเวอร์ชันปัจจุบัน เช่น bucket.objects.filter (Prefix = "myprefix /"). delete (); ตอนนี้ฉันเห็นเพียงเคอร์เซอร์กะพริบและฉันไม่รู้ว่าเกิดอะไรขึ้น
DJ_Stuffy_K

1
คุณจะต้องทำบางสิ่งบางอย่างเช่นfiles_to_delete = bucket.object_versions.filter(Prefix="myprefix/")จากนั้นวนซ้ำแล้วfiles_to_deleteเรียกพิมพ์ () จากนั้นลบ () บนสิ่งเหล่านี้
Dan-Dev

1

หากจำเป็นต้องกรองตามเนื้อหาวัตถุอย่างที่ฉันทำสิ่งต่อไปนี้คือพิมพ์เขียวสำหรับตรรกะของคุณ:

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})
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.