Smarter Vim Recovery?

When the previous Vim session crashed, you are greeted with a "swap file ... already exists!". for each file that was opened in a previous session.

Can you make this Vim recovery request smarter? (Without disabling recovery!) In particular, I think:

  • If the replacement version does not contain unsaved changes and the editing process no longer works, can you make Vim automatically delete the page file?
  • Can you automate the proposed process of saving the recovered file under a new name, merging it with a file on disk and then deleting the old paging file so that minimal interaction is required? Especially when the swap version and the disk version are the same, everything should be automatic.

I discovered the SwapExists auto SwapExists , but I don't know if it will help these tasks.

+46
vim recovery
Sep 15 '08 at 13:57
source share
7 answers

I have vim storing my paging files in one local directory, having this in my .vimrc:

 set directory=~/.vim/swap,. 

Among other benefits, this makes it easy to find swap files right away. Now that my laptop is losing power or something else, and I'm starting a backup with a bunch of swap files, I just run my cleanswap script:

 TMPDIR=$(mktemp -d) || exit 1 RECTXT="$TMPDIR/vim.recovery.$USER.txt" RECFN="$TMPDIR/vim.recovery.$USER.fn" trap 'rm -f "$RECTXT" "$RECFN"; rmdir "$TMPDIR"' 0 1 2 3 15 for q in ~/.vim/swap/.*sw? ~/.vim/swap/*; do [[ -f $q ]] || continue rm -f "$RECTXT" "$RECFN" vim -X -r "$q" \ -c "w! $RECTXT" \ -c "let fn=expand('%')" \ -c "new $RECFN" \ -c "exec setline( 1, fn )" \ -cw\! \ -c "qa" if [[ ! -f $RECFN ]]; then echo "nothing to recover from $q" rm -f "$q" continue fi CRNT="$(cat $RECFN)" if diff --strip-trailing-cr --brief "$CRNT" "$RECTXT"; then echo "removing redundant $q" echo " for $CRNT" rm -f "$q" else echo $q contains changes vim -n -d "$CRNT" "$RECTXT" rm -i "$q" || exit fi done 

This will delete any paging files that are relevant to real files. Any that do not match are displayed in the vimdiff window, so I can merge my unsaved changes.

- Chouser

+35
Sep 15 '08 at 14:20
source share

I just discovered this:

http://vimdoc.sourceforge.net/htmldoc/diff.html#:DiffOrig

I copied and pasted the DiffOrig command into my .vimrc file and it works like a charm. This makes paging file recovery much easier. I do not know why it is not enabled by default in VIM.

Here's a command for those in a hurry:

  command DiffOrig vert new | set bt=nofile | r # | 0d_ | diffthis \ | wincmd p | diffthis 
+20
Oct 21 '08 at 2:10
source share

The accepted answer is given as a very important precedent. Let's say you create a new buffer and type 2 hours without saving, then your laptop crashes. If you run the suggested script , it will delete your only entry, the swap file .swp . I'm not sure what the correct fix is, but it looks like the diff command will end up comparing the same file with itself. The modified version below checks this case and allows the user to save the file somewhere.

 #!/bin/bash SWAP_FILE_DIR=~/temp/vim_swp IFS=$'\n' TMPDIR=$(mktemp -d) || exit 1 RECTXT="$TMPDIR/vim.recovery.$USER.txt" RECFN="$TMPDIR/vim.recovery.$USER.fn" trap 'rm -f "$RECTXT" "$RECFN"; rmdir "$TMPDIR"' 0 1 2 3 15 for q in $SWAP_FILE_DIR/.*sw? $SWAP_FILE_DIR/*; do echo $q [[ -f $q ]] || continue rm -f "$RECTXT" "$RECFN" vim -X -r "$q" \ -c "w! $RECTXT" \ -c "let fn=expand('%')" \ -c "new $RECFN" \ -c "exec setline( 1, fn )" \ -cw\! \ -c "qa" if [[ ! -f $RECFN ]]; then echo "nothing to recover from $q" rm -f "$q" continue fi CRNT="$(cat $RECFN)" if [ "$CRNT" = "$RECTXT" ]; then echo "Can't find original file. Press enter to open vim so you can save the file. The swap file will be deleted afterward!" read vim "$CRNT" rm -f "$q" else if diff --strip-trailing-cr --brief "$CRNT" "$RECTXT"; then echo "Removing redundant $q" echo " for $CRNT" rm -f "$q" else echo $q contains changes, or there may be no original saved file vim -n -d "$CRNT" "$RECTXT" rm -i "$q" || exit fi fi done 
+16
Apr 29 2018-11-11T00:
source share

The excellent DiffOrig tip is perfect. Here is the bash script that I use to run in every page file in the current directory:

 #!/bin/bash swap_files=`find . -name "*.swp"` for s in $swap_files ; do orig_file=`echo $s | perl -pe 's!/\.([^/]*).swp$!/$1!' ` echo "Editing $orig_file" sleep 1 vim -r $orig_file -c "DiffOrig" echo -n " Ok to delete swap file? [y/n] " read resp if [ "$resp" == "y" ] ; then echo " Deleting $s" rm $s fi done 

You could probably use some more error checking and quoting, but it has worked so far.

+4
Apr 24 '09 at 3:03
source share

I prefer not to set the VIM working directory in .vimrc. Here's a modification of the chouser script that copies paging files to the paging path on demand, checking for duplicates, and then checking them. It was written, rushed, do not forget to evaluate it before using it for practical use.

 #!/bin/bash if [[ "$1" == "-h" ]] || [[ "$1" == "--help" ]]; then echo "Moves VIM swap files under <base-path> to ~/.vim/swap and reconciles differences" echo "usage: $0 <base-path>" exit 0 fi if [ -z "$1" ] || [ ! -d "$1" ]; then echo "directory path not provided or invalid, see $0 -h" exit 1 fi echo looking for duplicate file names in hierarchy swaps="$(find $1 -name '.*.swp' | while read file; do echo $(basename $file); done | sort | uniq -c | egrep -v "^[[:space:]]*1")" if [ -z "$swaps" ]; then echo no duplicates found files=$(find $1 -name '.*.swp') if [ ! -d ~/.vim/swap ]; then mkdir ~/.vim/swap; fi echo "moving files to swap space ~./vim/swap" mv $files ~/.vim/swap echo "executing reconciliation" TMPDIR=$(mktemp -d) || exit 1 RECTXT="$TMPDIR/vim.recovery.$USER.txt" RECFN="$TMPDIR/vim.recovery.$USER.fn" trap 'rm -f "$RECTXT" "$RECFN"; rmdir "$TMPDIR"' 0 1 2 3 15 for q in ~/.vim/swap/.*sw? ~/.vim/swap/*; do [[ -f $q ]] || continue rm -f "$RECTXT" "$RECFN" vim -X -r "$q" \ -c "w! $RECTXT" \ -c "let fn=expand('%')" \ -c "new $RECFN" \ -c "exec setline( 1, fn )" \ -cw\! \ -c "qa" if [[ ! -f $RECFN ]]; then echo "nothing to recover from $q" rm -f "$q" continue fi CRNT="$(cat $RECFN)" if diff --strip-trailing-cr --brief "$CRNT" "$RECTXT"; then echo "removing redundant $q" echo " for $CRNT" rm -f "$q" else echo $q contains changes vim -n -d "$CRNT" "$RECTXT" rm -i "$q" || exit fi done else echo duplicates found, please address their swap reconciliation manually: find $1 -name '.*.swp' | while read file; do echo $(basename $file); done | sort | uniq -c | egrep '^[[:space:]]*[2-9][0-9]*.*' fi 
0
May 24 '13 at 20:16
source share

I have this in my .bashrc file. I would like to give an appropriate loan to parts of this code, but I forgot where I got it from.

 mswpclean(){ for i in `find -L -name '*swp'` do swpf=$i aux=${swpf//"/."/"/"} orif=${aux//.swp/} bakf=${aux//.swp/.sbak} vim -r $swpf -c ":wq! $bakf" && rm $swpf if cmp "$bakf" "$orif" -s then rm $bakf && echo "Swap file was not different: Deleted" $swpf else vimdiff $bakf $orif fi done for i in `find -L -name '*sbak'` do bakf=$i orif=${bakf//.sbak/} if test $orif -nt $bakf then rm $bakf && echo "Backup file deleted:" $bakf else echo "Backup file kept as:" $bakf fi done } 

I just run this at the root of my project and, if the file is different, it opens vim diff. Then the last saved file will be saved. To make it perfect, I just would have to replace the last:

 else echo "Backup file kept as:" $bakf 

something like

 else vim $bakf -c ":wq! $orif" && echo "Backup file kept and saved as:" $orif 

but I did not have time to check it.

Hope this helps.

0
Apr 11 '14 at 15:08
source share

find./-type f -name ". * sw [klmnop]" -delete

Credit: @Shwaydogg https://superuser.com/questions/480367/whats-the-easiest-way-to-delete-vim-swapfiles-ive-already-recovered-from

First go to the directory

0
Oct 06 '16 at 11:10
source share



All Articles