* Further cleanup on cpv script; add back a ln_or_cp function and use it to cp only when ln fails for all instances of linking/copying in the script; better handling of case where the unversioned dest file does not exist but version versions of the file DO exst. * cpv: remove local declarations to be Posix-compliant
108 lines
2.3 KiB
Bash
Executable File
108 lines
2.3 KiB
Bash
Executable File
#!/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
|