Cover V12, I04
apr2003.tar

Listing 3 tgzdir

#!/bin/bash
#
# tgzdir: backup directory objects
# Author: J. Alan Eldridge

ORIGDIR=$(/bin/pwd); export ORIGDIR
APPNAME=${0##*/};APPNAME=${APPNAME#-}; export APPNAME
# qw -- quote text; listfiles -- list files/dirs
qw() { echo \""$@"\"; }
warn() { echo "[$APPNAME:$$]" "****" "$@";}
error() { echo "[$APPNAME:$$]" "ERROR:" "$@";}
# chdir -- cd or die 
chdir() { cd "$1" || die cd $(qw $1) failed; }
listfiles() { ls -1 ${1:+"$@"} 2>/dev/null; }
# absdir -- abs path of dir, MUST exist, run in subshell.
absdir() { chdir "$1" && pwd; }

# application starts here

dateonly=0
linklatest=0
rename_dot=0
delete=0
vflg=0
defkeep=10
keep=$defkeep

backup_one_dir() {
    local rc=0
    local td="$2"
    local sd sb bkpatt ll sp last newer killcnt

    test ! -d "$1" && warn $(qw "$1"): not a directory. && return -1
    sd=$(absdir $(dirname "$1")) sb=$(basename "$1")

    tb=$(echo "$sb"| tr -s " " "_")
    test $rename_dot -ne 0 -a "${sb#.}" != "$sb" && tb=_${sb#.}
    bkpatt="$tb.[12][01][0-9][0-9][01][0-9][0-3][0-9]*.tar.gz"
    ll="$tb".latest.tar.gz
    tb="$tb".$BKUPDATE.tar.gz
    sp="$sd/$sb" tp="$td/$tb"

    cd "$td"
    nbackups=$(listfiles -r $bkpatt|wc -l)

    if test $nbackups -gt 0; then
        last=$(listfiles -r $bkpatt|head -n 1)    
        newer=$(find "$sp" -newer "$last" | wc -l)
        if test $newer -eq 0; then
            mv $last $tb; rm -f "$ll"
            test $linklatest -ne 0 && ln -s "$tb" "$ll"
            return 0
        fi
    fi

    cd "$sd"
    sb=${sb%/.}
    tar cpf "${tp%.gz}" "$sb/."; rc=$?
    if test $rc -ne 0; then
        rm -f "${tp%.gz}"
    else
        gzip $gzip_args "${tp%.gz}"; rc=$?
    fi
    cd "$td"

    if test $rc != 0; then
        warn backup of $(qw "$sp") failed.; rm -fr "$tp"
        test $delete -ne 0 && warn $(qw "$sp"): was not deleted.
        return $rc
    fi
    
    test $delete -ne 0 && rm -fr "$sp"
    killcnt=$(($nbackups - $keep + 1))
    test $killcnt -gt 0 && rm -f $(listfiles $bkpatt|head -n $killcnt)
    rm -f "$ll"
    test $linklatest -ne 0 && ln -s "$tb" "$ll"
    return 0
}

usage() {
    cat <<EOF
Usage: $APPNAME [options] file|dir ...

Options:
    -k|--keep <n>    keep <n> backups.
                        [default = $defkeep].
    -d|--dest <dir>    Set destination for backups.
                        [default is same dir as source]
    -r|--rename     Rename .thing to _thing.
    -D|--date-only    Don't put hour,min on backup file name.
    -l|--link|--latest     Create a link \$file.latest to
                point to the most recent backup.
    -X|--delete        Delete dir after backup.
    -x|--debug        Turn on shell script debugging.
    -v|--verbose    Not implemented.
EOF
    exit $1
}

while test $# -gt 0; do
    n=1; case "$1" in
        -x|--debug)set -x;;
        --)shift;break;;
        -k|--keep)n=2;keep="$2";;
        -d|--dest)n=2;target="$2";;
        -v|--verbose)vflg=1;;
        -l|--link|--latest)linklatest=1;;
        -r|--rename)rename_dot=1;;
        -D|--date-only)dateonly=1;;
        -X|--delete)delete=1;;
        -*)usage 1;;
        *)break;;
        esac; shift $n
done
test $# = 0 && usage 0
test $keep -lt 1 && keep=1 
if test -n "$target"; then
    mkdir -p $target
    target=$(absdir $target)
    test -d $target || die Destination $(qw $target): not a directory.
fi
BKUPDATE=$(date +%Y%m%d.%H%M)
test $dateonly -ne 0 && BKUPDATE=${BKUPDATE%.????}
for i in "$@"; do
    cd "$ORIGDIR"
    if test ! -e "$i"; then
        error $(qw "$i") does not exist.
    else
        backup_one_dir "$i" $(absdir ${target:-$(dirname "$i")})
    fi
done
#EOF