Bash script to delete after X bookmarks

I have a ZFS send script that generates bookmarks because it will use the last bookmark to continue send/recv operations should I need to delete all snapshots. Anyway, I found some datasets have 88 bookmarks, other 70 bookmarks. I think there are no performance issues, only the bookmark list command may drag.

Anyway, this script keeps the last 14 bookmarks. It finds all datasets under the given path.

Posted here if someone finds it useful in the future. It has a build-in cheeky --dry-run flag too.

#!/bin/bash

PARENT_DATASET="pool/dataset" # This script will list all datasets
KEEP_COUNT=7
DRY_RUN=0

# Parse arguments for --dry-run
for arg in "$@"; do
  if [[ "$arg" == "--dry-run" ]]; then
    DRY_RUN=1
  fi
done

echo "Cleaning bookmarks under $PARENT_DATASET, keeping the last $KEEP_COUNT bookmarks per dataset..."
if [[ $DRY_RUN -eq 1 ]]; then
  echo ">>> DRY RUN MODE - No deletions will be performed <<<"
fi

# Get all datasets
DATASETS=$(sudo zfs list -H -o name | grep "^${PARENT_DATASET}")

for DATASET in $DATASETS; do
  echo "Processing dataset: $DATASET"

  BOOKMARKS=$(sudo zfs list -t bookmark -o name -H | grep "^${DATASET}#" | sort)

  COUNT=$(echo "$BOOKMARKS" | wc -l)

  if (( COUNT <= KEEP_COUNT )); then
    echo "  Only $COUNT bookmarks found, nothing to delete."
    continue
  fi

  DELETE_COUNT=$(( COUNT - KEEP_COUNT ))

  echo "  Found $COUNT bookmarks, deleting $DELETE_COUNT oldest..."

  echo "$BOOKMARKS" | head -n "$DELETE_COUNT" | while read -r BM; do
    if [[ $DRY_RUN -eq 1 ]]; then
      echo "Would delete: $BM"
    else
      echo "Deleting bookmark: $BM"
      sudo zfs destroy "$BM"
    fi
  done
done

echo "Bookmark cleanup completed."