prune-files 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. #!/usr/bin/env bash
  2. # Remove all but the latest N versions of files matching given prefixes
  3. # Usage: prune-files -k 3 thisfileprefix [thatfileprefix]
  4. # Copyright 2021-2025 Bryan C. Roessler
  5. # Licensed under the Apache License, Version 2.0
  6. prune-files() {
  7. declare -ag PREFIXES
  8. declare -g KEEP_INT=1 # default number of files to keep
  9. printHelpAndExit() {
  10. cat <<-'EOF'
  11. USAGE:
  12. prune-files -k 3 thisfileprefix [thatfileprefix]
  13. OPTIONS:
  14. -k, --keep NUMBER
  15. Keep NUMBER of the latest files that match each file prefix (Default: 1)
  16. -h, --help
  17. Print this help dialog and exit
  18. EOF
  19. [[ -z "$1" ]] && exit 0 || exit "$1"
  20. }
  21. parseInput() {
  22. if _input=$(getopt -o hk: -l help,keep: -- "$@"); then
  23. eval set -- "$_input"
  24. while true; do
  25. case "$1" in
  26. -k|--keep) shift; KEEP_INT="$1" ;;
  27. -h|--help) printHelpAndExit 0 ;;
  28. --) shift; break ;;
  29. esac
  30. shift
  31. done
  32. else
  33. echo "Incorrect option(s) provided"
  34. printHelpAndExit 1
  35. fi
  36. PREFIXES=("$@")
  37. }
  38. findAndRemove() {
  39. local prefix file
  40. for prefix in "${PREFIXES[@]}"; do
  41. # List files matching the prefix sorted by modification time (latest first),
  42. # then remove all except the first KEEP_INT files.
  43. while IFS= read -r file; do
  44. echo "Removing: $file"
  45. rm -- "$file"
  46. done < <(
  47. find . -maxdepth 1 -type f -name "${prefix}*" -printf '%T@ %p\n' | \
  48. sort -rn | \
  49. awk -v keep="$KEEP_INT" 'NR > keep {print $2}'
  50. )
  51. done
  52. }
  53. main() {
  54. parseInput "$@"
  55. findAndRemove
  56. }
  57. main "$@"
  58. }
  59. # Allow script to be safely sourced
  60. if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
  61. prune-files "$@"
  62. exit $?
  63. fi