#!/bin/sh # cpv file dest # could extend with -r or copying multiple files #define ln_or_cp function - try to hardlink and if that fails copy source to dest ln_or_cp () { ln_or_cp_src="$1" ln_or_cp_dest="$2" ln "$ln_or_cp_src" "$ln_or_cp_dest" >/dev/null 2>&1 if [ $? -eq 0 ] then return 0 else cp -p "$ln_or_cp_src" "$ln_or_cp_dest" return $? fi } # end of funtion definitions file="$1" dest="$2" if [ ! -f "$file" ]; then echo "Error: no such file "$file". Exiting." exit 1 fi # if dest is a directory, add the source file name if [ -d "$dest" ]; then dest=$dest/`basename $file` fi # if (the new) $dest is a directory, then just bail if [ -d "$dest" ]; then echo "Error: destination file ($dest) is a directory. Exiting." exit 1 fi # if no such file $dest or dest.~[0-9]*~ then just link or copy # without adding version info # THEN EXIT if [ ! -f "$dest" ] && ! ls "$dest".~[0-9]*~ >/dev/null 2>&1 then ln_or_cp $file $dest res=$? if [ $res -eq 0 ] then msg_start="Added" else msg_start="Error: failed to add" fi echo "$msg_start $(basename $dest) to $(dirname $dest)" exit $res fi # find maximum version of dest max=0 for vf in "$dest".~[1-9]*~ do vn=`echo $vf | sed -e 's/^.*\.~\([1-9][0-9]*\)~$/\1/'` if [ -f $dest.~$vn~ ]; then if [ $max -lt $vn ]; then max=$vn fi fi done if [ $max -eq 0 ]; then # no current versions mv $dest $dest.~1~ # change version to version 1 new=2 else if cmp -q $dest $dest.~$max~ >/dev/null 2>&1 then # they're different max=`expr $max + 1` # make newer version mv $dest $dest.~$max~ new=`expr $max + 1` else # dest and dest.~nn~ are equal so rm $dest # delete dest leave old version behind new=`expr $max + 1` fi fi # make new version and link or copy it. # If link or copy fails, then exit with error code ln_or_cp $file $dest.~$new~ res=$? if [ $res -eq 0 ] then echo "Added $(basename $dest.~$new~) to $(dirname $dest.~$new~)" else echo "Error: failed to add $(basename $dest.~$new~) to $(dirname $dest.~$new~)." exit $res fi # hardlink latest version to unversioned filename rm -f $dest ln $dest.~$new~ $dest if [ $? -eq 0 ] then msg_start="Linked" else msg_start="Warning: failed to link" fi echo "$msg_start $(basename $dest) to $(basename $dest.~$new~) in $(dirname $dest)" exit 0