Tux

...making Linux just a little more fun!

2-cent Tip: File versioning/backup

Ben Okopnik [ben at linuxgazette.net]


Sat, 1 Nov 2008 23:32:43 -0400

[For some reason, I thought I'd submitted this ages ago; searching LG shows that I was apparently wrong.]

There are lots of times - e.g., when you're editing a critical file, or want to keep multiple versions of a script that you're developing - that you want to take a snapshot of your current directory, or at least of some of the files within it. I've been using the following script for the past several years, and it's proven to be flexible, powerful, and fully sufficient for the task.

Note that you can also define a ".backup" file within the directory (this should contain the names of the files to be backed up, one per line) so you can run "backup" without any arguments and still have it snapshoot the right files. Enjoy!

#!/bin/sh
# Created by Ben Okopnik on Wed Jan 26 21:48:05 EST 2005
 
name="`/usr/bin/printf $0|/bin/sed 's|.*/||'`"
 
usage () {
cat <<!
Usage:
	$name -h
	$name [-a] [file[s]]
	
	-h	Show this help
	-a	Back up all specified files unconditionally
	
	The list of files to be backed up can be defined either in a
	.backup file in the current directory, on the command line, or as a
	combination of the two. The files will be saved in a "backup"
	subdirectory, with a timestamp extension appended to their
	filenames.
 
	If the latest archived copy of a specified file does not differ
	from the current version, the file will not be backed up unless the
	"-a" option is used.
 
!
}
 
case "$1" in
	-h) usage; exit ;;
	-a) do_all=1; shift ;;
	-n) no_file=1; shift ;;
esac
 
 
backup () {
	# Create a backup directory if necessary
	[ -d "backup" ] || {
		[ -e "backup" ] && { 
			echo "Error: $PWD contains a file called 'backup': can't create a 'backup' directory!"
			exit
		}
		echo -n "Creating 'backup' directory... "
		mkdir backup
		[ "$?" -eq 0 ] && echo "Success!" || { echo "Failed - exiting."; exit; }
	}
 
	for file in "$@"
	do
		[ -f "$file" ] || { printf "$file not found!\n"; continue; }
		# Find the last backup for each file
		latest="`ls backup/$file.20[0-9]* 2>/dev/null|tail -1`"
		[ -z "$latest" ] && do_all=1
		if [ "$do_all" = "1" ] || [ -n "`diff -q $file $latest`" ]
		then
			cp -i "$file" "backup/$file.`date +'%Y%m%d%H%M%S'`"
			saved="$saved $file"
		else
			nodiff="$nodiff $file"
		fi
	done
 
	[ -n "$saved" ] && echo "Backed up: $saved"
	[ -n "$nodiff" ] && echo "NOT backed up (identical files in archive): $nodiff"
}
 
[ "$no_file" = 1 ] || { [ -f ".backup" ] && set "$@ `cat .backup`"; }
 
if [ -n "`echo $*|grep '[^ ]'`" ]
then
	backup $@
else
	echo "No files specified and no ./.backup file found; exiting."
	exit 1
fi
-- 
* Ben Okopnik * Editor-in-Chief, Linux Gazette * https://LinuxGazette.NET *


Top    Back


Michael Makuch [linuxgazette at makuch.org]


Mon, 03 Nov 2008 11:00:15 -0600

Ben Okopnik wrote:

> There are lots of times - e.g., when you're editing a critical file, or
> want to keep multiple versions of a script that you're developing - tha
>   

My solution to a similar need. I use a wrapper for vi which backs up every file edited. I've been using this for many years...

Enjoy | Ignore Mike

#!/bin/sh
     
files=$*
cwd=`pwd`
     
bakdir="$HOME/vibak"
ds=`date '+%y%m%d.%H%M%S'`
     
# backup each file
for file in $files
do  
    c=`echo $file|cut -c1-1`
    if [ "$c" != "/" ] ; then
        file="$cwd/$file"
    fi
    y=`echo $file|sed -e 's/\//_/g'`;
    if [ -f $file ] ; then
        cp $file $bakdir/$y.${ds}
        chown mkm $bakdir/$y.${ds}
        chmod u+w $bakdir/$y.${ds}
    fi
done
    
/usr/bin/vim $*
    
for file in $files
do  
    c=`echo $file|cut -c1-1`
    if [ "$c" != "/" ] ; then
        file="$cwd/$file"
    fi
    y=`echo $file|sed -e 's/\//_/g'`;
    if [ -f $bakdir/$y.${ds} ] ; then
        x=`diff $file $bakdir/$y.${ds}`
        if [ $? = 0 ] ; then
# if no change remove the backup copy
            rm $bakdir/$y.${ds}
        else   
# if changed then make a backup copy of the new file too
            cp $file $bakdir/$y
            chown mkm $bakdir/$y
            chmod a+rw $bakdir/$y
        fi     
    fi
done


Top    Back


Ben Okopnik [ben at linuxgazette.net]


Sun, 9 Nov 2008 21:22:37 -0500

On Mon, Nov 03, 2008 at 11:00:15AM -0600, Michael Makuch wrote:

> Ben Okopnik wrote:
> > There are lots of times - e.g., when you're editing a critical file, or
> > want to keep multiple versions of a script that you're developing - tha
> >   
> 
> My solution to a similar need. I use a wrapper for vi which backs up 
> every file
> edited. I've been using this for many years...

So, do you go in there once in a while and clean out the old files? It seems like, after a while, you'd have a lot of stuff in there including some huge files that would eat up all your disk space.

Also, have you looked at all the backup-related functionality that Vim provides? Try ':help backup'; there are lots of flexible options to do this, including time-stamped extensions. E.g. (in ~/.vimrc):

" Use a timestamp as a backup extension
au BufWritePre * let &bex = '-' . strftime("%Y-%b-%d-%X") . '~'
" Save backups in ~/tmp; fail over to /tmp in case of problems
set backupdir=~/tmp,/tmp
set backup
-- 
* Ben Okopnik * Editor-in-Chief, Linux Gazette * https://LinuxGazette.NET *


Top    Back


Neil Youngman [ny at youngman.org.uk]


Mon, 10 Nov 2008 08:18:32 +0000

On Monday 10 November 2008 02:22:37 Ben Okopnik wrote:

> So, do you go in there once in a while and clean out the old files? It
> seems like, after a while, you'd have a lot of stuff in there including
> some huge files that would eat up all your disk space.
>
> Also, have you looked at all the backup-related functionality that Vim
> provides? Try ':help backup'; there are lots of flexible options to do
> this, including time-stamped extensions. E.g. (in ~/.vimrc):

Neat.

Emacs provides numbered backups and automatic cleanup. My .emacs includes:

(setq version-control 't)		; make numbered backups
(setq vc-make-backup-files 't)		; keep backups for files in version control
(setq delete-old-versions 't)		; delete excess backups without asking
(setq kept-old-versions 2)		; keep the 2 oldest backups
(setq kept-new-versions 3)		; keep the 3 newest backups

Neil


Top    Back


Michael Makuch [mike8 at makuch.org]


Mon, 10 Nov 2008 08:04:48 -0600

Ben Okopnik wrote:

> On Mon, Nov 03, 2008 at 11:00:15AM -0600, Michael Makuch wrote:
>   
>> Ben Okopnik wrote:
>>     
>>> There are lots of times - e.g., when you're editing a critical file, or
>>> want to keep multiple versions of a script that you're developing - tha
>>>   
>>>       
>> My solution to a similar need. I use a wrapper for vi which backs up 
>> every file
>> edited. I've been using this for many years...
>>     
>
> So, do you go in there once in a while and clean out the old files? It
> seems like, after a while, you'd have a lot of stuff in there including
> some huge files that would eat up all your disk space.
>
> Also, have you looked at all the backup-related functionality that Vim
> provides? Try ':help backup'; there are lots of flexible options to do
> this, including time-stamped extensions. E.g. (in ~/.vimrc):
>
> ```
> " Use a timestamp as a backup extension
> au BufWritePre * let &bex = '-' . strftime("%Y-%b-%d-%X") . '~'
> " Save backups in ~/tmp; fail over to /tmp in case of problems
> set backupdir=~/tmp,/tmp
> set backup
> '''

Yes I clean it periodically but not very often. Right now there are ~3k files in my vibak dating back ~3 years and totaling ~700MB.

No I didn't know about the backup functions I'll check it out. Thanks.


Top    Back