Vim Tips Wiki
m (Incremental Auto-Backup moved to Keep incremental backups of edited files: Page moved by JohnBot to improve title)
(Change to TipImported template + severe manual clean)
Line 1: Line 1:
 
{{review}}
 
{{review}}
  +
{{TipImported
{{Tip
 
 
|id=892
 
|id=892
  +
|previous=891
|title=Incremental Auto-Backup
 
  +
|next=893
|created=March 9, 2005 6:19
 
  +
|created=March 9, 2005
 
|complexity=basic
 
|complexity=basic
 
|author=Tim Doerfler
 
|author=Tim Doerfler
 
|version=6.0
 
|version=6.0
 
|rating=19/13
 
|rating=19/13
  +
}}
|text=
 
  +
I was wondering how I could make an automatic backup of my edited files. I added the following to my vimrc:
Hello Everyone.
 
   
  +
<pre>
  +
set backupdir=c:\temp\vim_backup
  +
let myvar = strftime("(%y%m%d)[%Hh%M]")
  +
let myvar = "set backupext=_". myvar
  +
execute myvar
  +
</pre>
   
  +
So the command which is executed in this example sounds like this:
   
  +
<pre>
I was wondering how I could make an automatic backup of my edited files.
 
  +
set backupext=_(050309)[15h15]
  +
</pre>
   
  +
This creates backups into c:\temp\vim_backup\ having names like myfile_(050309)[15h15] instead of myfile~
I added the following to my _vimrc:
 
   
  +
Each time my vim starts up for editing a file, backupext gets changed so I get at least one backup per day, without overwriting backups of the day before.
   
  +
If I open and close that file more often, I could theoretically have one Backup each minute. ( But who would want to have that many backups ? )
   
  +
==Comments==
[snip]
 
  +
With the following mapping:
   
  +
<pre>
set backupdir=c:\temp\vim_backup
 
  +
fun! InitBex()
  +
let myvar = strftime("(%y%m%d)[%Hh%M]")
  +
let myvar = "set backupext=_". myvar
  +
execute myvar
  +
echo myvar
  +
endfun
  +
map &lt;ESC&gt; :call InitBex()&lt;CR&gt;
  +
</pre>
   
  +
You can easily refresh the backupextension time everytime you hit the &lt;ESC&gt; key. So you can get backups every minute, every hour, every day and so on.
let myvar = strftime("(%y%m%d)[%Hh%M]")
 
   
let myvar = "set backupext=_". myvar
 
 
execute myvar
 
 
[snap]
 
 
 
 
So the command which is executed in this example sounds like this:
 
 
 
 
set backupext=_(050309)[15h15]
 
 
 
 
This creates backups into c:\temp\vim_backup\ having names
 
 
like myfile_(050309)[15h15] instead of myfile~
 
 
 
 
Each time my vim starts up for editing a file, backupext gets changed so
 
 
I get at least one backup per day, without overwriting backups of the day
 
 
before.
 
 
 
 
If I open and close that file more often, I could theoretically have one Backup
 
 
each minute. ( But who would want to have that many backups ? )
 
 
 
 
 
}}
 
 
== Comments ==
 
Hi again.
 
With the following mapping ( simply insert it into _vimrc ):
 
 
[snip]
 
fun! InitBex()
 
let myvar = strftime("(%y%m%d)[%Hh%M]")
 
let myvar = "set backupext=_". myvar
 
execute myvar
 
echo myvar
 
endfun
 
map &lt;ESC&gt; :call InitBex()&lt;CR&gt;
 
[snap]
 
 
You can easily refresh the backupextension time everytime you hit the &lt;ESC&gt; key.
 
( Well this is VIM. You know that this key is hit VERY often ... :-) )
 
 
So you can get backups every minute, every hour, every day and so on ...
 
 
timicq--AT--web.de
 
, March 10, 2005 0:10
 
 
----
 
----
If having multiple backups interests you, you may also consider:
+
If having multiple backups interests you, you may also consider {{script|id=89}} savevers.vim by Ed Ralston or {{script|id=563}} rcsvers.vim by Juan Frias and Roger Pilkey.
 
savevers.vim by Ed Ralston ([/scripts/script.php?script_id=89 vimscript &#35;89])
 
 
or
 
 
rcsvers.vim by Juan Frias and Roger Pilkey(me) ([/scripts/script.php?script_id=563 vimscript &#35;563])
 
 
Roger
 
 
 
   
'''Anonymous'''
 
, March 10, 2005 9:29
 
 
----
 
----
If you guys need this kinda backup -- invest in version control (I recommend subversion).
+
If you guys need this kind of backup, invest in version control (I recommend subversion).
   
It is a cool trick, but it seems like you would generate a fairly massive number of files in a fairly short amount of time.
 
 
vi-improved.org
 
, March 13, 2005 21:06
 
 
----
 
----
You're right. But you can determine how many backups you get by changing the
+
You can determine how many backups you get by changing the backupext - String: If the backup - String contains minutes, you could get far too many backups ( maximum: one per minute ).
backupext - String: If the backup - String contains minutes, you could get
 
far too many backups ( maximum: one per minute ).
 
 
If you leave out the minutes, you get maximum one backup per hour.
 
Leave out the hours -&gt; one per day ...
 
 
We use version control for our standard - Software. But we do customizing, too
 
for our customers. And all these customized functions differ from the standard.
 
That's why I want a backup without using a CVS Tool
 
   
  +
If you leave out the minutes, you get maximum one backup per hour. Leave out the hours -&gt; one per day ...
Greetings,
 
   
  +
We use version control for our standard - Software. But we do customizing, too for our customers. And all these customized functions differ from the standard. That's why I want a backup without using a CVS Tool
Tim
 
   
timicq--AT--web.de
 
, March 14, 2005 2:39
 
 
----
 
----
If you are a sysadmin and trying to fix something, I think you *do* want that many backups. The drive space is cheap when compared with the cost of unnecesary downtime. I can always send the backups to my trash directory which is already managed. For that matter, I can probably set up logrotate to compress all of the text files in the users trash directories *and* delete the old ones.
+
If you are a sysadmin and trying to fix something, I think you *do* want that many backups. The drive space is cheap when compared with the cost of unnecesary downtime. I can always send the backups to my trash directory which is already managed. For that matter, I can probably set up logrotate to compress all of the text files in the users trash directories *and* delete the old ones.
   
jcllings--AT--javahop.com
 
, March 22, 2005 15:33
 
 
----
 
----
This seems to work for a backup each and every time the file has changed and it does so with a correctly dated and absolutely unique filename in the trash directory. mktemp gaurrenties uniqueness, if not my spelling. ;-) As for knowing when it was deleted, hey that's what we have file attributes for. A trash dumping utility would have to go by the file attributes anyway, right? So here we go:
+
This seems to work for a backup each and every time the file has changed and it does so with a correctly dated and absolutely unique filename in the trash directory. mktemp gaurrenties uniqueness, if not my spelling. ;-) As for knowing when it was deleted, hey that's what we have file attributes for. A trash dumping utility would have to go by the file attributes anyway, right? So here we go:
   
  +
<pre>
set backup
 
  +
set backup
  +
" in .vimrc right after the text: "
  +
"if has("autocmd") put this:"
  +
augroup backups
  +
au!
  +
"Note:Sorry, but this all goes on one line"
  +
autocmd BufWritePost,FileWritePost * !diff -d &lt;afile&gt; &lt;afile&gt;~ &amp;&gt; /dev/null;if [[ $? == 1 ]];then touch &lt;afile&gt;~;mv &lt;afile&gt;~ `mktemp ~/Desktop/Trash/&lt;afile&gt;.XXXXXX`;fi
  +
augroup END
  +
</pre>
   
  +
"Note: If you see something like this, you know it is working:"
" in .vimrc right after the text: "
 
"if has("autocmd") put this:"
 
   
  +
<pre>
augroup backups
 
  +
"leaves.txt" 182L, 2031C written
  +
:!diff -d leaves.txt leaves.txt~ &amp;&gt; /dev/null;if [[ $? == 1 ]];then mv leaves.txt~ `mktemp ~/Desktop/Trash/leaves.txt.XXXXXX`;fi
  +
</pre>
   
  +
OK, now let's discuss what it does:
au!
 
   
  +
<pre>
"Note:Sorry, but this all goes on one line"
 
  +
#This line turns on backups:
  +
set backup
   
  +
#This line declares a new auto command group named backups.
autocmd BufWritePost,FileWritePost * !diff -d &lt;afile&gt; &lt;afile&gt;~ &amp;&gt; /dev/null;if [[ $? == 1 ]];then touch &lt;afile&gt;~;mv &lt;afile&gt;~ `mktemp ~/Desktop/Trash/&lt;afile&gt;.XXXXXX`;fi
 
  +
augroup backups
   
  +
#Erase any extra garbage commands that might be lying around.
augroup END
 
  +
au!
   
  +
autocmd BufWritePost,FileWritePost * !diff -d &lt;afile&gt; &lt;afile&gt;~ &amp;&gt; /dev/null;if [[ $? == 1 ]];then touch &lt;afile&gt;~;mv &lt;afile&gt;~ `mktemp ~/Desktop/Trash/&lt;afile&gt;.XXXXXX`;fi
"Note: If you see something like this, you know it is working:"
 
   
  +
# Of course, this is the end of our one-liner augroup statement.
"leaves.txt" 182L, 2031C written
 
  +
augroup END
:!diff -d leaves.txt leaves.txt~ &amp;&gt; /dev/null;if [[ $? == 1 ]];then mv leaves.txt~ `mktemp ~/Desktop/Trash/leaves.txt.XXXXXX`;fi
 
  +
</pre>
   
  +
The above says create an new autocmd that will be executed when writing a file or buffer is finished. It will apply to files named "*". The bang (i.e. "!") identifies the command to be executed which comes next. The command itself is nothing more than a few BASH commands all on the same line. &lt;afile&gt; is the name of the affected file. Since we know that the name of the backup file is always "filename~", we can use &lt;afile&gt;~ to nail the backup file immediately after it has been written.
OK, now let's discuss what it does:
 
   
  +
I could have just as easily used a bash script to take care of this. It would have been much neater to look at but not as copyable and self contained. The script would have looked like this:
&#35;This line turns on backups:
 
set backup
 
   
  +
<pre>
&#35;This line declares a new auto command group named backups.
 
  +
#!/bin/bash
augroup backups
 
  +
#This script is named trash.sh
  +
diff -d $1 $2 &amp;&gt; /dev/null
  +
if [[ $? == 1 ]]
  +
then touch &lt;afile&gt;~
  +
mv $2 `mktemp ~/Desktop/Trash/$1.XXXXXX`
  +
fi
  +
</pre>
   
  +
If I were to decide to put this script in my command path and use it, my autocmd line would have looked like this:
&#35;Erase any extra garbage commands that might be lying around.
 
au!
 
   
  +
<pre>
autocmd BufWritePost,FileWritePost * !diff -d &lt;afile&gt; &lt;afile&gt;~ &amp;&gt; /dev/null;if [[ $? == 1 ]];then touch &lt;afile&gt;~;mv &lt;afile&gt;~ `mktemp ~/Desktop/Trash/&lt;afile&gt;.XXXXXX`;fi
 
  +
autocmd BufWritePost,FileWritePost * !trash.sh &lt;afile&gt; &lt;afile&gt;~
  +
</pre>
   
&#35; Of course, this is the end of our one-liner augroup statement.
 
augroup END
 
 
&#35;The above says create an new autocmd that will be executed when writing a file or buffer is finished. It will apply to files named "*". The bang (i.e. "!") identifies the command to be executed which comes next. The command itself is nothing more than a few BASH commands all on the same line. &lt;afile&gt; is the name of the affected file. Since we know that the name of the backup file is always "filename~", we can use &lt;afile&gt;~ to nail the backup file immediately after it has been written.
 
 
I could have just as easily used a bash script to take care of this. It would have been much neater to look at but not as copyable and self contained. The script would have looked like this:
 
 
&#35;!/bin/bash
 
&#35;This script is named trash.sh
 
 
diff -d $1 $2 &amp;&gt; /dev/null
 
 
if [[ $? == 1 ]]
 
 
then touch &lt;afile&gt;~
 
 
mv $2 `mktemp ~/Desktop/Trash/$1.XXXXXX`
 
 
fi
 
 
If I were to decide to put this script in my command path and use it, my autocmd line would have looked like this:
 
 
autocmd BufWritePost,FileWritePost * !trash.sh &lt;afile&gt; &lt;afile&gt;~
 
 
Well, anyway that's what I came by for. Thanks for the help, hehe. ;-)
 
 
jcllings--AT--javahop.com
 
, March 22, 2005 23:32
 
 
----
 
----
  +
I noticed that this doesn't work for vim (gvim) 6.4 and vim 7.0.
This is something vim should manage automatically,
 
users should not have to use convoluted solutions.
 
   
  +
With help from others I got it tested and working for gvim 7.0. I assume for 6.4 it also work, but didn't test it.
Why is the kill history limited to 10 registers?
 
I want all previous edits of my file to be saved
 
in some kind of junk box. usually I cut and paste
 
code that I deleted.
 
   
  +
The chars '[' and ']' are not working in strftime apparently, and therefore I used '{' and '}'
Sunita
 
, March 24, 2005 12:12
 
----
 
I noticed that this doesn't work for vim (gvim) 6.4 and vim 7.0
 
 
With help from others I got it tested and working for gvim 7.0.
 
I assume for 6.4 it also work, but didn't test it.
 
 
The char's '[' and ']' are not working in strftime apperantly,, and therefor I used '{' and '}'
 
 
Copy this into your _vimrc:
 
fun! NewInitBex()
 
let &amp;bex = '-' . strftime("(%Y%m%d)-{%H%M}")
 
endfun
 
 
And in stead of mapping the ESC char I used the autocmd BufWritePre
 
autocmd BufWritePre * call NewInitBex()
 
 
 
'''Anonymous'''
 
, November 13, 2006 0:17
 
----
 
maybe it works if you escape the [ ] signs:
 
   
  +
Copy this into your _vimrc:
   
  +
<pre>
let &amp;bex = '-' . strftime("(%Y%m%d)-\[%H%M\]")
 
  +
fun! NewInitBex()
  +
let &amp;bex = '-' . strftime("(%Y%m%d)-{%H%M}")
  +
endfun
  +
</pre>
   
  +
And instead of mapping the ESC char I used:
   
  +
<pre>
  +
autocmd BufWritePre * call NewInitBex()
  +
</pre>
   
timicq&#35;web:de
 
, November 24, 2006 6:58
 
 
----
 
----
  +
Maybe it works if you escape the [ ] characters:
of course I meant the [] CHARACTERS...
 
   
  +
<pre>
OK I admit that I am from Germany ...
 
  +
let &amp;bex = '-' . strftime("(%Y%m%d)-\[%H%M\]")
  +
</pre>
   
timicq&#35;web:de
 
, November 24, 2006 7:00
 
 
----
 
----
<!-- parsed by vimtips.py in 0.537953 seconds-->
 

Revision as of 10:08, 1 December 2007

Tip 892 Printable Monobook Previous Next

created March 9, 2005 · complexity basic · author Tim Doerfler · version 6.0


I was wondering how I could make an automatic backup of my edited files. I added the following to my vimrc:

set backupdir=c:\temp\vim_backup
let myvar = strftime("(%y%m%d)[%Hh%M]")
let myvar = "set backupext=_". myvar
execute myvar

So the command which is executed in this example sounds like this:

set backupext=_(050309)[15h15]

This creates backups into c:\temp\vim_backup\ having names like myfile_(050309)[15h15] instead of myfile~

Each time my vim starts up for editing a file, backupext gets changed so I get at least one backup per day, without overwriting backups of the day before.

If I open and close that file more often, I could theoretically have one Backup each minute. ( But who would want to have that many backups ? )

Comments

With the following mapping:

fun! InitBex()
 let myvar = strftime("(%y%m%d)[%Hh%M]")
 let myvar = "set backupext=_". myvar
 execute myvar
 echo myvar
endfun
map <ESC> :call InitBex()<CR>

You can easily refresh the backupextension time everytime you hit the <ESC> key. So you can get backups every minute, every hour, every day and so on.


If having multiple backups interests you, you may also consider script#89 savevers.vim by Ed Ralston or script#563 rcsvers.vim by Juan Frias and Roger Pilkey.


If you guys need this kind of backup, invest in version control (I recommend subversion).


You can determine how many backups you get by changing the backupext - String: If the backup - String contains minutes, you could get far too many backups ( maximum: one per minute ).

If you leave out the minutes, you get maximum one backup per hour. Leave out the hours -> one per day ...

We use version control for our standard - Software. But we do customizing, too for our customers. And all these customized functions differ from the standard. That's why I want a backup without using a CVS Tool


If you are a sysadmin and trying to fix something, I think you *do* want that many backups. The drive space is cheap when compared with the cost of unnecesary downtime. I can always send the backups to my trash directory which is already managed. For that matter, I can probably set up logrotate to compress all of the text files in the users trash directories *and* delete the old ones.


This seems to work for a backup each and every time the file has changed and it does so with a correctly dated and absolutely unique filename in the trash directory. mktemp gaurrenties uniqueness, if not my spelling. ;-) As for knowing when it was deleted, hey that's what we have file attributes for. A trash dumping utility would have to go by the file attributes anyway, right? So here we go:

set backup
" in .vimrc right after the text: "
"if has("autocmd") put this:"
augroup backups
 au!
"Note:Sorry, but this all goes on one line"
autocmd BufWritePost,FileWritePost * !diff -d <afile> <afile>~ &> /dev/null;if [[ $? == 1 ]];then touch <afile>~;mv <afile>~ `mktemp ~/Desktop/Trash/<afile>.XXXXXX`;fi
augroup END

"Note: If you see something like this, you know it is working:"

"leaves.txt" 182L, 2031C written
:!diff -d leaves.txt leaves.txt~ &> /dev/null;if [[ $? == 1 ]];then mv leaves.txt~ `mktemp ~/Desktop/Trash/leaves.txt.XXXXXX`;fi

OK, now let's discuss what it does:

#This line turns on backups:
set backup

#This line declares a new auto command group named backups.
augroup backups

#Erase any extra garbage commands that might be lying around.
 au!

autocmd BufWritePost,FileWritePost * !diff -d <afile> <afile>~ &> /dev/null;if [[ $? == 1 ]];then touch <afile>~;mv <afile>~ `mktemp ~/Desktop/Trash/<afile>.XXXXXX`;fi

# Of course, this is the end of our one-liner augroup statement.
augroup END

The above says create an new autocmd that will be executed when writing a file or buffer is finished. It will apply to files named "*". The bang (i.e. "!") identifies the command to be executed which comes next. The command itself is nothing more than a few BASH commands all on the same line. <afile> is the name of the affected file. Since we know that the name of the backup file is always "filename~", we can use <afile>~ to nail the backup file immediately after it has been written.

I could have just as easily used a bash script to take care of this. It would have been much neater to look at but not as copyable and self contained. The script would have looked like this:

#!/bin/bash
#This script is named trash.sh
diff -d $1 $2 &> /dev/null
if [[ $? == 1 ]]
 then touch <afile>~
 mv $2 `mktemp ~/Desktop/Trash/$1.XXXXXX`
fi

If I were to decide to put this script in my command path and use it, my autocmd line would have looked like this:

autocmd BufWritePost,FileWritePost * !trash.sh <afile> <afile>~

I noticed that this doesn't work for vim (gvim) 6.4 and vim 7.0.

With help from others I got it tested and working for gvim 7.0. I assume for 6.4 it also work, but didn't test it.

The chars '[' and ']' are not working in strftime apparently, and therefore I used '{' and '}'

Copy this into your _vimrc:

fun! NewInitBex()
  let &bex = '-' . strftime("(%Y%m%d)-{%H%M}")
endfun

And instead of mapping the ESC char I used:

autocmd BufWritePre * call NewInitBex()

Maybe it works if you escape the [ ] characters:

let &bex = '-' . strftime("(%Y%m%d)-\[%H%M\]")