Last active
March 5, 2024 09:53
-
-
Save wknapik/191619bfa650b8572115cd07197f3baf to your computer and use it in GitHub Desktop.
Empty an s3 bucket of all object versions and delete markers in batches of 400
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
set -eEo pipefail | |
shopt -s inherit_errexit >/dev/null 2>&1 || true | |
if [[ ! "$#" -eq 2 || "$1" != --bucket ]]; then | |
echo -e "USAGE: $(basename "$0") --bucket <bucket>" | |
exit 2 | |
fi | |
# $@ := bucket_name | |
empty_bucket() { | |
local -r bucket="${1:?}" | |
for object_type in Versions DeleteMarkers; do | |
local opt=() next_token="" | |
while [[ "$next_token" != null ]]; do | |
page="$(aws s3api list-object-versions --bucket "$bucket" --output json --max-items 400 "${opt[@]}" \ | |
--query="[{Objects: ${object_type}[].{Key:Key, VersionId:VersionId}}, NextToken]")" | |
objects="$(jq -r '.[0]' <<<"$page")" | |
next_token="$(jq -r '.[1]' <<<"$page")" | |
case "$(jq -r .Objects <<<"$objects")" in | |
'[]'|null) break;; | |
*) opt=(--starting-token "$next_token") | |
aws s3api delete-objects --bucket "$bucket" --delete "$objects";; | |
esac | |
done | |
done | |
} | |
empty_bucket "${2#s3://}" |
When you have files with very long name, it will fail with Argument list too long
, even with a very low bunch of --max-items
So I rewrite a bit your function. Thanks anyway, it helps ! so I share mine. It's very slow as it loop over each file, but at least it works
function empty_bucket() {
for object_type in Versions DeleteMarkers; do
aws s3api list-object-versions \
--bucket "${BUCKET_NAME}" \
--output json \
--query="[{Objects: ${object_type}[].{Key:Key, VersionId:VersionId}}]" > /tmp/${object_type}.json
is_null=$(jq -c '.[0].Objects' /tmp/${object_type}.json)
if [ "${is_null}" = "null" ]; then
echo "Nothing to clean-up for ${object_type}"
else
jq -r -c '.[].Objects[] | .VersionId, .Key' /tmp/${object_type}.json | while read -r version && read -r key; do
aws s3api delete-object \
--bucket "${BUCKET_NAME}" \
--key "${key}" \
--version-id "${version}" \
--no-paginate \
--no-cli-pager \
--output text
done
fi
done
}
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@zishanj I only ever needed to delete them all, to be able to delete the bucket. But you could probably achieve that just by modifying the page query on line 18.
@bitlifter thanks for the hint, I lowered the number in the script.