#!/bin/bash # Archive/Backup file(s) # # This program copies the named file(s) to an archive directory. Version numbers # are appended to archived files, beginning with version 000. The lastest # version of a file is linked to a file with its same name -- the name without # the version number. # # A log file named LOG is kept of all the files archived. It has the file's original path, # the date it was archived, and it has a comment that is asked for from the user if it # is not specified on the command line. # # This version tries to save files in a common archive shared by a login group # located in /var/archive. If the directory /var/archive/GROUP_NAME does not exist, # the archive is located in the user's home directory. # # Copyright 1989-2019, Mack Pexton (mack@mackpexton.com) # License: https://opensource.org/licenses/mit-license.php USAGE="Usage: ${0##*/} [ -a ] [ -l ] [ -ccomment ] [ file_name ... ]" GROUP_ARCHIVE=/var/archive/$(id -gn) # group archive directory path USER_ARCHIVE=~/archive # personal archive directory path if [ -d "$GROUP_ARCHIVE" ] then archive_dir="$GROUP_ARCHIVE" else archive_dir="$USER_ARCHIVE" fi log="$archive_dir/LOG" user="${REMOTE_USER:-$(id -un)}" # used to brand comments in log file if [ ! -d "$archive_dir" ] then # Initialize archive. mkdir -m771 "$archive_dir" || exit 1 > "$log" chmod 666 "$log" fi for arg do case "$arg" in -a) echo "$archive_dir" ;; -c*) comment=${arg#-c} ;; # like: -c"This is a Comment" -l) cat "$log" ;; -*) echo "$USAGE" 1>&2; exit 1 ;; *) # Argument is a file name. if [ -d "$arg" ] then # Do nothing for directories echo "$arg is a directory. Only regular files can be archived." elif [ -e "$arg" ] then # Get user comment to record in log file. if [ -z "$comment" ] then echo -n "Comment: " read comment fi file_name="${arg##*/}" # Determine source file's absolute path. src="$arg"; if [ ${arg:0:1} != '/' ] then src="$(pwd)/$src" fi ( cd "${archive_dir}" # Find next available version number for archive file. # 0 fill the number to 3 places. typeset v=0 while vv=$(echo $v | sed -e 's/^/000/' -e 's/.*\(...\)$/\1/') test -a "${file_name}.${vv}" do v=$[ v+1 ] done archive_file="${file_name}.${vv}" # Copy file to archive file. cp --preserve -- "$src" "${archive_file}" # Link last archive version to archive file name (w/o version). if [ -a "${file_name}" ] then rm -f -- "${file_name}" fi ln -s -- "${archive_file}" "${file_name}" # Make archive file readonly. chmod a-w -- "${archive_file}" # Write archive details to log file. echo >> $log \ "$archive_file $(date +"%m/%d/%y %H:%M") $user $src $comment" ) else echo "File $arg not found." 1>&2 fi ;; esac done