postgres-archive/archive.sh
2024-12-19 00:16:41 -06:00

130 lines
2.8 KiB
Bash
Executable file

#!/usr/bin/env sh
# printc(args, description)
# Helper function to properly format text
printc() {
args="$1"
cmd="$2"
printf ' %s' "$1"
yes '' | head -n "$((20-${#args}))" | tr \\n ' '
printf '%s' "$cmd"
echo
}
# usage()
# Display usage information
usage() {
echo "usage: tartar [-0..9] [--level N] [--format F] DIR"
echo "Creates a compressed tape archive of every subdirectory in a given directory"
echo
echo "positional arguments:"
printc "DIR" "the directory to archive"
echo
echo "parameters:"
printc "-f, --format" "the compression format to use. default: xz"
printf '%44s %s\n' "options: gzip, xz"
printc "-0..-9, --level" "the level of compression to use: default 6"
echo
echo "environment variables:"
printc "ARCHIVE_DIR" "same as positional argument DIR"
printc "COMPRESSION_FORMAT" "same as --format"
printc "COMPRESSION_LEVEL" "same as --level"
}
includes() {
test="$1"
shift
for x in "$@"; do
if test "$test" = "$x"; then
return 0
fi
done
return 1
}
FORMATS="gzip xz"
LEVELS="0 1 2 3 4 5 6 7 8 9"
COMPRESSION_FORMAT="xz"
COMPRESSION_LEVEL="-6"
set_format() {
if includes "$1" "$FORMATS"; then
COMPRESSION_FORMAT="$1"
fi
}
set_level() {
if includes "$1" "$LEVELS"; then
COMPRESSION_LEVEL="-$1"
fi
}
parse_args() {
POSITIONAL_ARGS=""
# parse args
while [ $# -gt 0 ]; do
case $1 in
-f|--format)
set_format "$2"
shift
shift
;;
--level)
set_level "$2"
shift
shift
;;
-0|-1|-2|-3|-4|-5|-6|-7|-8|-9)
COMPRESSION_LEVEL="$1"
shift
;;
-h|--help)
usage
exit 0
;;
*)
POSITIONAL_ARGS="$POSITIONAL_ARGS $1"
shift # past argument
;;
esac
done
# drop the first space
POSITIONAL_ARGS=$( echo "$POSITIONAL_ARGS" | tail -c +2 )
}
can_archive() {
if test ! -f "${1}/backup.done"; then
echo "skipping $1; it is either incomplete or corrupted"
return 1
fi
if test ! -f "${1}/compression.done" || \
test ! -f "${1}.tar.xz" || \
! sha1sum -sc "${1}/compression.done"; then
return 0
else
return 1
fi
}
parse_args "$@"
# get the first positional argument, trim whitespace
dir=$( echo "$POSITIONAL_ARGS" | cut -d' ' -f1 | xargs )
dir=${dir:-"$ARCHIVE_DIR"}
cd "$dir" || exit 1
for dir in ./*/; do
dir="${dir%*/}"
if can_archive "$dir"; then
fname="$(basename $dir).tar.xz"
tar cv --exclude='*.done' "$dir" | "$COMPRESSION_FORMAT" "$COMPRESSION_LEVEL" > "$fname"
sha1sum "$fname" > "${dir}/compression.done"
fi
done