Как рекурсивно удалять файлы из корзины S3

87

У меня в S3 следующая структура папок. Есть ли способ рекурсивно удалить все файлы в определенной папке (скажем foo/bar1 or foo or foo/bar2/1..)

foo/bar1/1/..
foo/bar1/2/..
foo/bar1/3/..

foo/bar2/1/..
foo/bar2/2/..
foo/bar2/3/..
прия
источник

Ответы:

164

С помощью новейших инструментов командной строки python aws-cli рекурсивное удаление всех файлов в папке в корзине просто:

aws s3 rm --recursive s3://your_bucket_name/foo/

Или удалите все, что находится под ведром:

aws s3 rm --recursive s3://your_bucket_name

Если вы действительно хотите удалить корзину, есть одношаговый ярлык:

aws s3 rb --force s3://your_bucket_name

который будет рекурсивно удалить содержимое этого ведра, а затем удалить его.

Примечание: s3://для работы этих команд требуется префикс протокола.

number5
источник
2
это должен быть ответ. Это (новый) стандартный, мощный инструмент, разработанный для таких вещей, как этот вопрос
Дон Чидл
Это просто удаляет файлы, но также удаляет корзину после удаления файлов. Я что-нибудь пропустил?
Naveen
1
@Naveen, как я сказал выше, rmудалит только файлы, но rb --forceудалит файлы и корзину.
number5
5
использование также --recursiveудаляет папку.
ryantuck
1
@Moseleyi, я считаю, что на самом деле у вас не может быть пустой папки в ведре s3
ryantuck
58

Раньше это требовало специального вызова API для каждого ключа (файла), но было значительно упрощено благодаря внедрению Amazon S3 - Multi-Object Delete в декабре 2011 года:

Новое средство Multi-Object Delete в Amazon S3 дает вам возможность удалить до 1000 объектов из корзины S3 с помощью одного запроса.

См. Мой ответ на связанный вопрос: удалить из S3 с использованием api php с использованием подстановочного знака, чтобы получить дополнительную информацию об этом и соответствующих примерах в PHP ( AWS SDK для PHP поддерживает это, начиная с версии 1.4.8 ).

Тем временем большинство клиентских библиотек AWS так или иначе внедрили специальную поддержку этой функции, например:

Python

Вы можете добиться этого с помощью отличного интерфейса Boto Python для AWS примерно следующим образом (непроверено, из верхней части моей головы):

import boto
s3 = boto.connect_s3()
bucket = s3.get_bucket("bucketname")
bucketListResultSet = bucket.list(prefix="foo/bar")
result = bucket.delete_keys([key.name for key in bucketListResultSet])

Рубин

Эта функция доступна начиная с версии 1,24 из AWS SDK для Ruby , и примечания к выпуску дают пример , а также:

bucket = AWS::S3.new.buckets['mybucket']

# delete a list of objects by keys, objects are deleted in batches of 1k per
# request.  Accepts strings, AWS::S3::S3Object, AWS::S3::ObectVersion and 
# hashes with :key and :version_id
bucket.objects.delete('key1', 'key2', 'key3', ...)

# delete all of the objects in a bucket (optionally with a common prefix as shown)
bucket.objects.with_prefix('2009/').delete_all

# conditional delete, loads and deletes objects in batches of 1k, only
# deleting those that return true from the block
bucket.objects.delete_if{|object| object.key =~ /\.pdf$/ }

# empty the bucket and then delete the bucket, objects are deleted in batches of 1k
bucket.delete!

Или:

AWS::S3::Bucket.delete('your_bucket', :force => true)
Штеффен Опель
источник
следует использовать новый aws cliответ like @ number5
Дон Чидл,
43

Вы также можете рассмотреть возможность использования Amazon S3 Lifecycle для создания срока действия файлов с префиксом foo/bar1.

Откройте консоль браузера S3 и щелкните корзину. Затем щелкните «Свойства», а затем «Жизненный цикл».

Создайте правило истечения срока для всех файлов с префиксом foo/bar1и установите дату на 1 день с момента создания файла.

Сохраните, и все подходящие файлы будут удалены в течение 24 часов.

Только не забудьте удалить правило после того, как закончите!

Никаких вызовов API, никаких сторонних библиотек, приложений или скриптов.

Я просто так удалил несколько миллионов файлов.

Снимок экрана, показывающий окно правила жизненного цикла (обратите внимание, что на этом снимке префикс оставлен пустым, что влияет на все ключи в корзине):

введите описание изображения здесь

Райан
источник
4
Отличная идея для использования жизненного цикла вместо какой-то команды удаления.
xis
Совершенно верно, пусть S3 сделает это за вас.
Райан
Вы также можете применить это ко всему сегменту, что позволит удалить его.
Indolering
8

С s3cmdпакетом, установленным на машине Linux, вы можете сделать это

s3cmd rm s3://foo/bar --recursive

MichaelZ
источник
1
Согласно справке это либо удаление одного объекта, s3cmd del s3://BUCKET/OBJECTлибо удаление целого ведра s3cmd rb s3://BUCKET. Нет s3cmd rm, по крайней мере согласно s3cmd --help.
Пол Макмерди,
s3cmd rmнаходится в справке с 2019 года (как псевдоним del), это отличный ответ. Инструменты awscli работают только с /префиксом завершения, но не с префиксом папки и частичным префиксом имени файла, тогда как s3cmd работает в обоих случаях. Этот ответ требует гораздо больше голосов, мне пришлось слишком далеко прокручивать, чтобы найти правильное решение.
Дэвид Паркс
8

Если вы хотите удалить все объекты с префиксом "foo /" с помощью Java AWS SDK 2.0

import java.util.ArrayList;
import java.util.Iterator;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.*;

//...

ListObjectsRequest listObjectsRequest = ListObjectsRequest.builder()
    .bucket(bucketName)
    .prefix("foo/")
    .build()
;
ListObjectsResponse objectsResponse = s3Client.listObjects(listObjectsRequest);

while (true) {
    ArrayList<ObjectIdentifier> objects = new ArrayList<>();

    for (Iterator<?> iterator = objectsResponse.contents().iterator(); iterator.hasNext(); ) {
        S3Object s3Object = (S3Object)iterator.next();
        objects.add(
            ObjectIdentifier.builder()
                .key(s3Object.key())
                .build()
        );
    }

    s3Client.deleteObjects(
        DeleteObjectsRequest.builder()
            .bucket(bucketName)
            .delete(
                Delete.builder()
                    .objects(objects)
                    .build()
            )
            .build()
    );

    if (objectsResponse.isTruncated()) {
        objectsResponse = s3Client.listObjects(listObjectsRequest);
        continue;
    }

    break;
};
мужик
источник
1
Я не могу найти более убедительной демонстрации того, что людям не нравится в Java, чем этот ответ ...
Дживан
3

В случае использования AWS-SKD для ruby ​​V2.

s3.list_objects(bucket: bucket_name, prefix: "foo/").contents.each do |obj|
  next if obj.key == "foo/" 
  resp = s3.delete_object({
    bucket: bucket_name,
    key: obj.key,
  })
end

внимание пожалуйста, все "foo / *" в ведре удалятся.

Хадзиме
источник
2

Я просто удалил все файлы из своей корзины с помощью PowerShell:

Get-S3Object -BucketName YOUR_BUCKET | % { Remove-S3Object -BucketName YOUR_BUCKET -Key $_.Key -Force:$true }
Веласкец
источник
Спасибо за отправку этого ответа, я пытался сделать именно это и поставил -Key «% _. Key», который не работает.
Скотт Гартнер,
1

В проголосованном ответе отсутствует шаг.

Per aws s3 help:

В настоящее время не поддерживается использование подстановочных знаков стиля UNIX в аргументах пути команды. Тем не менее, большинство команд имеют --exclude "<value>"и --include "<value>" параметры , которые можно достичь желаемого результата ......... Если есть несколько фильтров, правило фильтры , которые появляются позже в команде, превалируют над фильтрами , которые появляются ранее в команде. Например, если параметры фильтра, переданные в команду, были: --exclude "*" --include "*.txt"Все файлы будут исключены из команды, кроме файлов с расширением .txt.

aws s3 rm --recursive s3://bucket/ --exclude="*" --include="/folder_path/*" 
Einarc
источник
0

Лучший способ - использовать правило жизненного цикла для удаления всего содержимого корзины. Программно вы можете использовать следующий код (PHP) для правила жизненного цикла PUT.

$expiration = array('Date' => date('U', strtotime('GMT midnight')));
$result = $s3->putBucketLifecycle(array(
            'Bucket' => 'bucket-name',
            'Rules' => array(
                array(
                    'Expiration' => $expiration,
                    'ID' => 'rule-name',
                    'Prefix' => '',
                    'Status' => 'Enabled',
                ),
            ),
        ));

В этом случае все объекты будут удалены. Дата начала - «Сегодня полночь по Гринвичу».

Вы также можете указать Дни следующим образом. Но с Днями он будет ждать не менее 24 часов (минимум 1 день), чтобы начать удаление содержимого корзины.

$expiration = array('Days' => 1);
Шриганеш Шинтре
источник
0

Мне нужно было сделать следующее ...

def delete_bucket
  s3 = init_amazon_s3
  s3.buckets['BUCKET-NAME'].objects.each do |obj|
    obj.delete
  end
end

def init_amazon_s3
  config = YAML.load_file("#{Rails.root}/config/s3.yml")
  AWS.config(:access_key_id => config['access_key_id'],:secret_access_key => config['secret_access_key'])
  s3 = AWS::S3.new
end
Imdad
источник