Initial commit
This commit is contained in:
104
scripts/prune-files
Executable file
104
scripts/prune-files
Executable file
@@ -0,0 +1,104 @@
|
||||
#!/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
|
||||
Reference in New Issue
Block a user