104 lines
2.6 KiB
Bash
Executable File
104 lines
2.6 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Remove all but the latest N versions of files matching given prefixes
|
|
# Usage: prune-files -k 3 thisfileprefix [thatfileprefix]
|
|
|
|
set -euo pipefail
|
|
|
|
prune-files() {
|
|
local -a PREFIXES
|
|
local KEEP_INT=1 # default number of files to keep
|
|
local DRY_RUN=false
|
|
|
|
printHelpAndExit() {
|
|
cat <<-'EOF'
|
|
USAGE:
|
|
prune-files -k 3 thisfileprefix [thatfileprefix]
|
|
|
|
OPTIONS:
|
|
-k, --keep NUMBER
|
|
Keep NUMBER of the latest files that match each file prefix (Default: 1)
|
|
-n, --dry-run
|
|
Show what would be removed without actually deleting files
|
|
-h, --help
|
|
Print this help dialog and exit
|
|
EOF
|
|
[[ -z "$1" ]] && exit 0 || exit "$1"
|
|
}
|
|
|
|
parseInput() {
|
|
local _input
|
|
if _input=$(getopt -o hk:n -l help,keep:,dry-run -- "$@"); then
|
|
eval set -- "$_input"
|
|
while true; do
|
|
case "$1" in
|
|
-k|--keep) shift; KEEP_INT="$1" ;;
|
|
-n|--dry-run) DRY_RUN=true ;;
|
|
-h|--help) printHelpAndExit 0 ;;
|
|
--) shift; break ;;
|
|
esac
|
|
shift
|
|
done
|
|
else
|
|
echo "[ERROR] Incorrect option(s) provided" >&2
|
|
printHelpAndExit 1
|
|
fi
|
|
|
|
if [[ $# -eq 0 ]]; then
|
|
echo "[ERROR] At least one file prefix must be provided" >&2
|
|
printHelpAndExit 1
|
|
fi
|
|
|
|
if ! [[ "$KEEP_INT" =~ ^[0-9]+$ ]] || [[ "$KEEP_INT" -lt 1 ]]; then
|
|
echo "[ERROR] --keep must be a positive integer" >&2
|
|
exit 1
|
|
fi
|
|
|
|
PREFIXES=("$@")
|
|
}
|
|
|
|
findAndRemove() {
|
|
local prefix file count
|
|
|
|
for prefix in "${PREFIXES[@]}"; do
|
|
count=0
|
|
echo "[INFO] Processing files with prefix: $prefix"
|
|
|
|
# List files matching the prefix sorted by modification time (latest first),
|
|
# then remove all except the first KEEP_INT files.
|
|
while IFS= read -r file; do
|
|
if [[ "$DRY_RUN" == true ]]; then
|
|
echo "[DRY-RUN] Would remove: $file"
|
|
else
|
|
echo "[INFO] Removing: $file"
|
|
if ! rm -- "$file"; then
|
|
echo "[ERROR] Failed to remove: $file" >&2
|
|
fi
|
|
fi
|
|
((count++))
|
|
done < <(
|
|
find . -maxdepth 1 -type f -name "${prefix}*" -printf '%T@ %p\n' 2>/dev/null | \
|
|
sort -rn | \
|
|
awk -v keep="$KEEP_INT" 'NR > keep {print $2}'
|
|
)
|
|
|
|
if [[ $count -eq 0 ]]; then
|
|
echo "[INFO] No files to remove for prefix: $prefix"
|
|
else
|
|
echo "[INFO] Processed $count file(s) for prefix: $prefix"
|
|
fi
|
|
done
|
|
}
|
|
|
|
main() {
|
|
parseInput "$@"
|
|
findAndRemove
|
|
}
|
|
|
|
main "$@"
|
|
}
|
|
|
|
# Allow script to be safely sourced
|
|
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
|
|
prune-files "$@"
|
|
exit $?
|
|
fi |